题意:
给出递推式 (F):
[F(0)=0,F(1)=1
]
[F(n)=3*F(n-1)+2*F(n-2)(ngeq2)
]
给出查询次数:(Q) 和第一次查询的数 (N),每次查询的答案为:(A_i=F(N))。并且(N_i=N_{i-1} xor A_{i-1}^2),最后要求输出:(A_1 xor A_2 ... xor A_Q)。
题目链接:https://nanti.jisuanke.com/t/41355
分析:
(1) (N) 的范围很大,直接算肯定算不出来,但因为数据比较水,所以用 (map) 记忆化一下就可以。
代码:
#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
typedef long long ll;
unordered_map<ll,ll>mp;
struct matrix
{
ll mat[3][3];
void zero()
{
for(int i=1;i<=2;i++)
for(int j=1;j<=2;j++)
mat[i][j]=0;
}
void eye()
{
for(int i=1;i<=2;i++)
mat[i][i]=1;
}
matrix operator * (const matrix &mt)const
{
matrix res;
res.zero();
for(int i=1;i<=2;i++)
{
for(int k=1;k<=2;k++)
{
if(mat[i][k])
{
for(int j=1;j<=2;j++)
res.mat[i][j]=(res.mat[i][j]+mat[i][k]*mt.mat[k][j]%mod)%mod;
}
}
}
return res;
}
};
matrix mpower(matrix m,ll b)
{
matrix res;
res.zero();
res.eye();
while(b)
{
if(b&1) res=res*m;
m=m*m;
b>>=1;
}
return res;
}
void init(matrix &a)
{
a.zero();
a.mat[1][1]=1;
}
void init2(matrix &a)
{
a.zero();
a.mat[1][1]=3;
a.mat[1][2]=1;
a.mat[2][1]=2;
}
int main()
{
ll a,ans=0,q,n;
scanf("%lld%lld",&q,&n);
matrix A,B,t;
init(A);
init2(B);
while(q--)
{
if(mp.count(n))
a=mp[n];
else
t=A*mpower(B,n-1);
a=t.mat[1][1];
mp[n]=a;
n=n^(a*a);
ans=ans^a;
}
printf("%lld
",ans);
return 0;
}
(2)可以求出循环节求解
(3)斐波那契数列的通项公式:
[F(n)=frac{1}{sqrt{17}}(frac{3+sqrt{17}}{2})^n-frac{1}{sqrt{17}}(frac{3-sqrt{17}}{2})^n
]
(sqrt{17}) 在模 (p) 意义下等价于 (17) 模 (p) 的二次剩余,本题中这个值存在且是一个整数;但依然会多一个快速幂的 (log),这里 (n) 可以用欧拉降幂降到 (2e9) 以内。
设 (N=sqrt{2e9}) ,(n=k*N+r),有 (x^n=x^{k*N}*x^r),注意到 (kleq N,rleq N),预处理出最后的两部分就可以 (O(1)) 查询出 (F(n))。