一道不错的题,教会我好多新套路。
首先得到递推式的特征方程
x 2 − 233 x − 666 = 0 x ^ 2 - 233 x - 666=0 x2−233x−666=0
易得 x = 233 ± 13 337 2 x= \frac{233 \pm 13 \sqrt{337}}{2} x=2233±13337
设通项式 A n = a x 1 n + b x 2 n A_n=ax_1^n+bx_2^n An=ax1n+bx2n
因为 A 0 = 0 , A 1 = 1 A_0=0,A_1=1 A0=0,A1=1
所以
{ a + b = 0 a x 1 + b x 2 = 1 \begin{cases}\begin{array}{}a+b=0\\ax_1+bx_2=1\end{array}\end{cases} {a+b=0ax1+bx2=1
解得
{ a = 1 13 337 b = − 1 13 337 \begin{cases}\begin{array}{}a=\frac{1}{13\sqrt{337}}\\b=-\frac{1}{13\sqrt{337}}\end{array}\end{cases} {a=133371b=−133371
于是得通项式 A n = 1 13 337 ( ( 233 + 13 337 2 ) n − ( 233 − 13 337 2 ) n ) A_n=\dfrac{1}{13\sqrt{337}}((\dfrac{233+13 \sqrt{337}}{2})^n-(\dfrac{233-13 \sqrt{337}}{2})^n) An=133371((2233+13337)n−(2233−13337)n)
用 B S G S BSGS BSGS求二次剩余,不难解得在 m o d    1000000007 \mod{1000000007} mod1000000007 时,通项式为
A n ≡ 233230706 ( 9415303 5 n − 90584720 5 n ) ( m o d    1000000007 ) A_n \equiv 233230706 ( 94153035 ^ n - 905847205 ^ n )(\mod 1000000007) An≡233230706(94153035n−905847205n)(mod1000000007)
考虑到快速幂带 l o g log log,无法通过本题。。。
然而因为模数为奇质数
于是根据费马小定理,显然任意数的幂都有长度为 1000000006 1000000006 1000000006的循环节,因此指数被缩小到 1000000006 1000000006 1000000006的范围
又因为底数与模数确定
所以我们可以选取一个与 1000000006 \sqrt{1000000006} 1000000006同阶的数 m m m,预处理出 x 0 , x 1 , . . . , x m − 1 x^0,x^1,...,x^ { m - 1 } x0,x1,...,xm−1和 x 0 , x m , . . . , x m 2 x^0,x^m,...,x^{m^2} x0,xm,...,xm2
然后对于每一个询问 x k x^k xk, O ( 1 ) O(1) O(1)求 x ⌊ k / m ⌋ × x k m o d    m x^{\lfloor k / m \rfloor} \times x^{k\mod{m}} x⌊k/m⌋×xkmodm即可
于是此题得解。。。
#include<cstdio>
const int P=1000000007;
const int a=233230706,b1=94153035,b2=905847205;
const int BLOCK_SIZE=32768;
int hbp1[BLOCK_SIZE],lbp1[BLOCK_SIZE];
int hbp2[BLOCK_SIZE],lbp2[BLOCK_SIZE];
void init()
{
lbp1[0]=1;
for(int i=1;i<BLOCK_SIZE;++i)lbp1[i]=(long long)lbp1[i-1]*b1%P;
hbp1[0]=1;
hbp1[1]=(long long)lbp1[BLOCK_SIZE-1]*b1%P;
for(int i=2;i<BLOCK_SIZE;++i)hbp1[i]=(long long)hbp1[i-1]*hbp1[1]%P;
lbp2[0]=1;
for(int i=1;i<BLOCK_SIZE;++i)lbp2[i]=(long long)lbp2[i-1]*b2%P;
hbp2[0]=1;
hbp2[1]=(long long)lbp2[BLOCK_SIZE-1]*b2%P;
for(int i=2;i<BLOCK_SIZE;++i)hbp2[i]=(long long)hbp2[i-1]*hbp2[1]%P;
}
int power1(int k)
{
return (long long)hbp1[k/BLOCK_SIZE]*lbp1[k%BLOCK_SIZE]%P;
}
int power2(int k)
{
return (long long)hbp2[k/BLOCK_SIZE]*lbp2[k%BLOCK_SIZE]%P;
}
namespace Mker
{
unsigned long long SA,SB,SC;
void init(){scanf("%llu%llu%llu",&SA,&SB,&SC);}
unsigned long long rand()
{
SA^=SA<<32,SA^=SA>>13,SA^=SA<<1;
unsigned long long t=SA;
SA=SB,SB=SC,SC^=t^SA;return SC;
}
}
int main()
{
int T;
scanf("%d",&T);
init();
Mker::init();
int res=0;
while(T--)
{
int n=Mker::rand()%1000000006;
res^=(long long)a*(power1(n)-power2(n)+P)%P;
}
printf("%d",res);
}