网址: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;
}