题意简述
已知 (a_n=233a_{n-1}+666a_{n-2},a_0=0,a_1=1)
有 (5 imes 10^7) 组询问,求 (a_n) 模 (10^9+7) 的值
题解思路
必须要 (O(1)) 实现
设 (a_n=ccdot q^n),
则 $ c cdot q^n=233c cdot q^{n-1}+666c cdot q^{n-2}$
化简后得 (q^2-233q-666=0),解得 (q_1= frac{233+sqrt{56953}}{2}),(q_2= frac{233-sqrt{56953}}{2})
然后可以发现 (sqrt{56953}) 在模 (10^9+7) 意义下恰好等于 (188305837)
在模意义下 (q_1=94153035),(q_2=905847205)
所以 (a_n=c_1cdot q_1^n-c_2cdot q_2^n),将 (a_0=0,a_1=1)带入,
即 (egin{cases} c_1-c_2=0 \ c_1cdot q_1-c_2cdot q_2=1end{cases}) 解得 (c_1=c_2=frac{1}{q1-q2}) 在模意义下即 (233230706)
所以 (a_n=233230706 imes(94153035^n-905847205^n))
此时用快速幂仍然会T,由于底数固定,所以可以分块。
取(S=lceilsqrt{n_{max}} ceil),这里为了方便取 (S=2^{16}=65536)
对于每一个(n),都可以表示为(kcdot S+r,k∈[0,S),r∈[0,S))
所以分别预处理出 (f_1[k]=q_1^k,kin[0,S)) 和 (f_2[k]=q_1^{kcdot S},kin[0,S)),则(q^n=f_1[n/S]*f2[n\%S]=f_1[n>>16]*f1[n&S])。
(q_2)同理,这样就可以(O(1))求出答案
代码
#include <cstdio>
#define ll long long
#define ull unsigned ll
const int mod=1e9+7,S=65535,c1=94153035,c2=905847205,c3=233230706;
int T,ans;
ll f11[S+5]={1},f12[S+5]={1},f21[S+5]={1},f22[S+5]={1};
ull SA,SB,SC,t;
inline ull rnd() {
SA^=SA<<32,SA^=SA>>13,SA^=SA<<1;
t=SA,SA=SB,SB=SC; return SC^=t^SA;
}
int main() {
scanf("%d%llu%llu%llu",&T,&SA,&SB,&SC);
for (int i=1;i<=S;++i) f11[i]=f11[i-1]*c1%mod,f21[i]=f21[i-1]*c2%mod;
const int x1=f11[S]*c1%mod,x2=f21[S]*c2%mod;
for (int i=1;i<=S;++i) f12[i]=f12[i-1]*x1%mod,f22[i]=f22[i-1]*x2%mod;
for (;T;--T) {
t=rnd()%(mod-1); const int t1=t&S,t2=t>>16;
ans^=((f11[t1]*f12[t2]-f21[t1]*f22[t2])%mod+mod)*c3%mod;
}
printf("%d
",ans);
}