题目描述 传送门
For a series FFF:
We have some queries. For each query N, the answer A is the value F(N) modulo 998244353.
Moreover, the input data is given in the form of encryption, only the number of queries Q and the first query N1 are given. For the others, the query Ni(2≤i≤Q) is defined as the xor of the previous Ni and the square of the previous answer Ai−1. For example, if the first query N1 is 2, the answer A1 is 3, then the second query N2 is 2 xor (3∗3)=11.
Finally, you don't need to output all the answers for every query, you just need to output the xor of each query's answer A1 xor A2...xor AQ.
Input
The input contains two integers,Q, N, 1 ≤ Q≤10^7, 0 ≤ N≤10^18. Q representing the number of queries and N representing the first query.
Output:
An integer representing the final answer.
样例输入
17 473844410
样例输出
903193081
思路:矩阵快速幂 + map, 正在这些F(N) Mod 998244353 的结果是有一定的循环的(猜想),但是其周期不好把握。于是我就用了这个map 把算过的F(N) 记录下来,下次再用的时候可以直接使用,而不用再调用矩阵快速幂了。这样就节省了不少时间。顺利AC。
AC代码
#include <bits/stdc++.h>
using namespace std;
#define io ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define mset(a, n) memset(a, n, sizeof(a))
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef long long ll;
typedef pair<int,int> PII;
typedef pair<int,PII> PPI;
typedef pair<ll, ll> PLL;
const int maxn = 2e5+5;
const ll Mod = 998244353;
ll Q, N;
map<ll, ll> ma;
struct Mat{ // 2X2 的矩阵
ll x0, x1, x2, x3;
};
Mat mul(Mat A, Mat B){ // C = A*B
Mat C;
C.x0 = ( (A.x0*B.x0%Mod + A.x1*B.x2%Mod)%Mod );
C.x1 = ( (A.x0*B.x1%Mod + A.x1*B.x3%Mod)%Mod );
C.x2 = ( (A.x2*B.x0%Mod + A.x3*B.x2%Mod)%Mod );
C.x3 = ( (A.x2*B.x1%Mod + A.x3*B.x3%Mod)%Mod );
return C;
}
Mat Qpow(Mat A, ll mi){
Mat res0; res0.x0 = (1), res0.x1 = (0), res0.x2 = (0), res0.x3 = (1);
while(mi>0){
if(mi&1){
res0 = mul(res0, A);
}
A = mul(A, A);
mi>>=1;
}
return res0;
}
int main(){
cin>>Q>>N;
ll ans = 0, A0;
Mat A; A.x0=3, A.x1 = 2, A.x2 = 1, A.x3 = 0;
Mat res;
for(int i = 1;i<=Q; i++){
if(ma[N] == 0){ // 优化在这里
res = Qpow(A, N-1ll);
A0 = res.x0;
ma[N] = A0;
}
else res.x0 = ma[N];
N = N^(A0*A0);
ans ^= A0;
}
cout<<ans<<'\n';
return 0;
}
/*
170000 473844410
*/