[洛谷P5107]能量采集
题目大意:有一张$n(n\leqslant50)$个点$m(m\leqslant n(n-1))$条边的有向图,每个点还有一个自环,每个点有一个权值。每一秒钟,每个点的权值会等分成出边个数,流向出边。$q(q\leqslant5\times10^4)$次询问,每次问$t$秒时每个点的权值,只需要输出异或和
题解:矩阵快速幂,可以构造出转移矩阵,发现直接做的复杂度是$O(qn^3\log_2t)$,不可以通过。
然后预处理转移矩阵的$2^i$次幂,就可以$O(n^2)$完成一次转移(向量乘矩阵),这样复杂度是$O(qn^2log_2t)$,看起来不可以通过本题,但其实也可以了。
题解中说是把预处理中的二进制改成$k$进制,这样复杂度是$O(n^3k\log_kt+qn^2\log_kt)$
卡点:无
C++ Code:
#include <cstdio> #include <cctype> namespace __IO { namespace R { int x, ch; inline int read() { while (isspace(ch = getchar())) ; for (x = ch & 15; isdigit(ch = getchar()); ) x = x * 10 + (ch & 15); return x; } } } using __IO::R::read; #define maxn 50 const int mod = 998244353; namespace Math { inline int pw(int base, int p) { static int res; for (res = 1; p; p >>= 1, base = static_cast<long long> (base) * base % mod) if (p & 1) res = static_cast<long long> (res) * base % mod; return res; } inline int inv(int x) { return pw(x, mod - 2); } } struct Matrix { #define N 50 int n, m; int s[N][N]; inline Matrix operator * (const Matrix &rhs) { Matrix res; res.n = n, res.m = rhs.m; for (register int i = 0; i < n; ++i) { for (register int j = 0; j < rhs.m; ++j) { static long long t; t = 0; for (register int k = 0; k < m; ++k) t += static_cast<long long> (s[i][k]) * rhs.s[k][j] % mod; res.s[i][j] = t % mod; } } return res; } #undef N } I, base[32], ans; int n, m, q; int oud[maxn]; int main() { n = read(), m = read(), q = read(); for (int i = 0; i < n; ++i) I.s[0][i] = read(), base[0].s[i][i] = 1, oud[i] = 1; I.n = 1, I.m = n; while (m --> 0) { int a = read() - 1, b = read() - 1; ++base[0].s[a][b]; ++oud[a]; } base[0].n = base[0].m = n; for (int i = 0, t; i < n; ++i) { t = Math::inv(oud[i]); for (int j = 0; j < n; ++j) base[0].s[i][j] = static_cast<long long> (t) * base[0].s[i][j] % mod; } for (int i = 1; i < 32; ++i) base[i] = base[i - 1] * base[i - 1]; while (q --> 0) { Matrix res = I; for (int i = read(); i; i &= i - 1) res = res * base[__builtin_ctz(i)]; int ans = 0; for (int i = 0; i < n; ++i) ans ^= res.s[0][i]; printf("%d\n", ans % mod); } return 0; }