[洛谷P5107]能量採集
阿新 • • 發佈:2019-01-12
題目大意:有一張$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; }