线性递推函数的循环节是mod+1,但还是被卡时间,所以先把1-1e7中的F函数放到内存中,用矩阵快速幂提前处理出1e7~100e7的幂的特征矩阵,这样每次回答寻用只用O(1)的时间
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<ll> vec;
typedef vector<vec> mat;
const ll mod=998244353;
const ll Max=1e7;
ll FFF[Max+10];
mat mul(mat& A, mat& B){
mat C(A.size(), vec(B[0].size()));
for (int i = 0; i < A.size(); i++)
for (int k = 0; k < B.size(); k++)
if (A[i][k]) // 对稀疏矩阵的优化
for (int j = 0; j < B[0].size(); j++)
C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % mod;
return C;
}
mat Pow(mat A, ll n){
mat B(A.size(), vec(A.size()));
for (int i = 0; i < A.size(); i++) B[i][i] = 1;
for (; n; n >>= 1, A = mul(A, A))
if (n & 1) B = mul(B, A);
return B;
}
mat MMM[110];
int main(){
FFF[0]=0;FFF[1]=1;
mat B(2,vec(2));
B[0][0]=0;B[0][1]=2;B[1][0]=1;B[1][1]=3;
for(int i=2;i<=Max;++i)FFF[i]=(FFF[i-1]*3+FFF[i-2]*2)%mod;
for(ll i=1;i<=100;++i){MMM[i]=Pow(B,i*Max);}
mat A(1,vec(2));
int Q;ll n;cin>>Q>>n;
int res=0;
for(int i=1;i<=Q;++i){
int x=n%(mod-1);
if(x==0){
res=res^0;
n=n^0;
break;
}if(x==1){
res=res^1;
n=n^1;
continue;
}
if(x<=Max){
int ans=FFF[x];
res=res^ans;
n=n^(1ll*ans*ans);
continue;
}
int y=x%Max;
int z=x/Max;
int ans=(1ll*MMM[z][0][1]*FFF[y-1]+MMM[z][1][1]*FFF[y])%mod;
res=res^ans;
n=n^(1ll*ans*ans);
}
cout<<res<<endl;
}