#特征方程,光速幂#洛谷 5110 块速递推
题目
给定一个数列满足\(a_n=233a_{n-1}+666a_{n-2},a_0=0,a_1=1\)
\(T\)组询问求\(a_n \bmod {10^9+7},T\leq 5\times 10^7\)
分析
首先这道题可以用矩阵快速幂+预处理分块做(不放博客迁移前的链接了),
但是为了锻炼特征方程就来重新做一做这题
首先我们要找到一组\(p,q\)使得\(a_n=(p+q)a_{n-1}+pq\times a_{n-2}\)
然后根据推导得到
\[a_n=\frac{a_1-pa_0}{q-p}q^n+\frac{a_1-qa_0}{p-q}p^n
\]
解出来就是
\[p=\frac{233+\sqrt{56953}}{2},q=\frac{233-\sqrt{56953}}{2}
\]
凡是做了一下二次剩余或者推出来的,应该都知道
\(188305837^2\equiv 56953 \pmod {10^9+7}\)
最后化简得到
\[a_n=233230706(94153035^n-905847205^n)\bmod {10^9+7}
\]
光速幂(分块预处理)一下就可以做到\(O(T)\)了
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
typedef unsigned long long ull; ull sa,sb,sc,temp;
const int A=94153035,B=905847205,C=233230706,mod=1000000007,N=32768;
int T,n,ans,Aa[N+7],Ab[N+7],Ba[N+7],Bb[N+7];
inline signed ksm(int x,int y){
rr int ans=1;
for (;y;y>>=1,x=1ll*x*x%mod)
if (y&1) ans=1ll*ans*x%mod;
return ans;
}
signed main(){
Aa[0]=Ab[0]=Ba[0]=Bb[0]=1,scanf("%d",&T);
for (rr int i=1;i<=N;++i) Aa[i]=1ll*Aa[i-1]*A%mod;
for (rr int i=1;i<=N;++i) Ba[i]=1ll*Ba[i-1]*B%mod;
for (rr int i=1;i<=N;++i) Ab[i]=1ll*Ab[i-1]*Aa[N]%mod;
for (rr int i=1;i<=N;++i) Bb[i]=1ll*Bb[i-1]*Ba[N]%mod;
for (scanf("%llu%llu%llu",&sa,&sb,&sc);T;--T){
sa^=sa<<32,sa^=sa>>13,sa^=sa<<1,
temp=sa,sa=sb,sb=sc,sc^=temp^sa,n=sc%(mod-1);
rr int t1=1ll*Ab[n>>15]*Aa[n&32767]%mod;
rr int t2=1ll*Bb[n>>15]*Ba[n&32767]%mod;
ans^=1ll*C*(t1-t2+mod)%mod;
}
return !printf("%d",ans);
}