題目鏈接:https://nanti.jisuanke.com/t/41355
分段打表。。
將一個ll整數分成三部分:
123456789123456789:123456 789123 456789
將這三部分的矩陣冪分別預處理出來。
很秀的打表方法。。。。
代碼:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=2,mod=998244353 ;
const int N=1e6;
struct Matrix
{
ll mat[MAXN][MAXN];
Matrix() {}
Matrix operator*(Matrix const &b)const
{
Matrix res;
memset(res.mat, 0, sizeof(res.mat));
for (int i = 0 ;i < MAXN; i++)
for (int j = 0; j < MAXN; j++)
for (int k = 0; k < MAXN; k++)
res.mat[i][j] = (res.mat[i][j]+this->mat[i][k] * b.mat[k][j])%mod;
return res;
}
};
Matrix pre[4][2*N+10];
Matrix base,fi;
ll f(ll n)
{
if(n<=1) return n;
n--;
int ty=0;int f=0;
Matrix ans;
while(n&&ty<3)
{
++ty;
ll k=n%N;
if(ty==3) k=n;
if(k)
{
if(f) ans=ans*pre[ty][k];
else ans=pre[ty][k];
f=1;
}
n/=N;
}
return ans.mat[0][0];
}
void init()
{
base.mat[0][0] = 3;
base.mat[0][1] = 2;
base.mat[1][0] = 1;
pre[1][1]=base;
for(int i=2;i<=N;++i) pre[1][i]=pre[1][i-1]*pre[1][1];
pre[2][1]=pre[1][N];
for(int i=2;i<=N;++i) pre[2][i]=pre[2][i-1]*pre[2][1];
pre[3][1]=pre[2][N];
for(int i=2;i<=2*N;++i) pre[3][i]=pre[3][i-1]*pre[3][1];
}
int main()
{
init();
int q;
ll n;
scanf("%d%lld",&q,&n);
ll t=0,a;
for(int i=1;i<=q;i++)
{
a=f(n);
n=n^(a*a);
t^=a;
}
printf("%lld\n",t);
return 0;
}