注意到对于询问,如果对 E 进行快速幂的话,由于 E 是 n \times n 的矩阵,因此做一次的复杂度就为 O(n^3)。但是 F 是 1 \times n 的矩阵,因此 F 每次异或一个 E 的幂的复杂度为 O(n^2)。考虑不进行快速幂,对 a_i 进行二进制拆分,拆成 O(\log a) 个 2 的幂的形式 ,首先预处理出 E^{2^k} 的值,然后用 F 依次乘上对应的幂即可。
另外回复一下评论区疑问,上式复杂度中的 - 不代表减号。对于一个算法,用 A-B 表示其预处理部分为 A 的复杂度,B 表示其余部分的时间复杂度。
Code
namespace Fusu {
const int maxt = 32;
const int maxn = 105;
int n, q, m;
ll a[maxn];
struct Mat {
int x, y;
ll mt[maxn][maxn];
Mat(const int X = 0, const int Y = 0) : x(X), y(Y) {}
Mat operator*(const Mat &o) const {
Mat ret(x, o.y);
for (int i = 1; i <= x; ++i) {
for (int j = 1; j <= o.y; ++j) {
ret.mt[i][j] = 0;
for (int k = 1; k <= y; ++k) {
ret.mt[i][j] ^= mt[i][k] * o.mt[k][j];
}
}
}
return ret;
}
};
Mat g[maxt], f;
void Main() {
qr(n); qr(m); qr(q);
qra(a + 1, n);
g[0].x = g[0].y = n;
for (int u, v; m; --m) {
qr(u); qr(v);
g[0].mt[u][v] = g[0].mt[v][u] = 1;
}
for (int i = 1, di = i - 1; i < maxt; di = i++) {
g[i] = g[di] * g[di];
}
for (ll x; q; --q) {
qr(x);
f.x = 1; f.y = n;
memcpy(f.mt[1] + 1, a + 1, n * sizeof(ll));
for (ll w = 1, i = 0; w <= x; w <<= 1, ++i) if (x & w) {
f = f * g[i];
}
qw(f.mt[1][1], '\n');
}
}
} // namespace Fusu