2019南昌网络赛H The Nth Item 矩阵快速幂
网址:https://nanti.jisuanke.com/t/41355
题意:
求$Q$次$F(n)mod998244353$的所有值的异或,$F(n)$由递推公式给出,且必须在线,$Q \leq 1e7$。
题解:
看到形如$F(n)=a*F(n-1)+b*F(n-2)$的式子,就是矩阵快速幂的套路,直接矩阵快速幂求出来,然后按照题意模拟即可。矩阵快速幂和数的快速幂同理,只不过刚开始的$res=1$换成单位矩阵即可。实测$1e7$会超时,加上记忆化即可通过。
AC代码:
#include <bits/stdc++.h> #pragma GCC optimize(3) using namespace std; typedef long long ll; const int mod = 998244353; const int MAXN = 1e7 + 5; unordered_map<int, ll>mp; struct Mat { ll m[2][2]; }; Mat mul(Mat a, Mat b) { Mat tmp; memset(tmp.m, 0, sizeof(tmp.m)); tmp.m[0][0] = (a.m[0][0] * b.m[0][0] % mod + a.m[0][1] * b.m[1][0] % mod) % mod; tmp.m[0][1] = (a.m[0][0] * b.m[0][1] % mod + a.m[0][1] * b.m[1][1] % mod) % mod; tmp.m[1][0] = (a.m[1][0] * b.m[0][0] % mod + a.m[1][1] * b.m[1][0] % mod) % mod; tmp.m[1][1] = (a.m[1][0] * b.m[0][1] % mod + a.m[1][1] * b.m[1][1] % mod) % mod; return tmp; } Mat inv(Mat a,ll n) { Mat res; memset(res.m, 0, sizeof(res.m)); for (int i = 0; i < 2; ++i) res.m[i][i] = 1; while (n) { if (n & 1) res = mul(res, a); a = mul(a, a); n >>= 1; } return res; } Mat beg, b, mtmp; void init() { memset(beg.m, 0, sizeof(beg.m)); beg.m[0][0] = 1; b.m[0][0] = 3; b.m[0][1] = 1; b.m[1][0] = 2; } int main() { ll q, n, ans = 0; init(); scanf("%lld%lld", &q, &n); for (int i = 1; i <= q; ++i) { ll tmp; if (!mp.count(n)) { mtmp = mul(beg, inv(b, n - 1)); tmp = mtmp.m[0][0] % mod; mp[n] = tmp; } else tmp = mp[n]; ans ^= tmp; tmp %= mod; n ^= tmp * tmp; } printf("%lld\n", ans); return 0; }