正题
这题太难了。
能想出怎么构造都难
首先构造,根据
,可以得到
,从而可以得到
多出来一个2的常数很丑陋,尝试利用来把它消除。
设,可以得到
,那么有两组解:
。
不妨令其等于前者,可以得到,
。
不妨令,设
,可以得到
,那么我们如果能快速求出t那么就可以求出答案。
发现就是 t 的递推式中特征方程的两个根,根据韦达定理还原出原方程为
。
即可以得到,其中
,用矩阵快速幂优化即可。
当然也可以用
发现要求第项,但是没办法高精度,所以一定要找到一个循环节。
根据论文,一个二阶递推式求循环节,可以通过判断二次剩余的形式,来求得循环节。
具体可以先做一做斐波那契的循环节这一题,可以记住一些定理,在这里,的循环节一定是
的约数,直接处理即可。
#include<bits/stdc++.h>
using namespace std;
int T;
long long n,mod;
struct Matrix{
long long v[2][2];
friend Matrix operator *(const Matrix A,const Matrix B){
Matrix C;
memset(C.v,0,sizeof(C.v));
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
(C.v[i][j]+=A.v[i][k]*B.v[k][j]%mod)%=mod;
return C;
}
}d,p;
__int128 ksm(__int128 x,__int128 t,__int128 mod){
__int128 tot=1;
while(t){
if(t&1) (tot*=x)%=mod;
(x*=x)%=mod;
t/=2;
}
return tot;
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%lld %lld",&n,&mod);
if(mod==3 || mod==2 || mod==6) {printf("1\n");continue;}
d.v[1][0]=d.v[0][1]=0;d.v[0][0]=d.v[1][1]=1;
p.v[0][0]=11,p.v[0][1]=1,p.v[1][0]=mod-1,p.v[1][1]=0;
long long t=ksm(2,n-1,mod*mod-1);t--;
while(t){
if(t&1) d=d*p;
p=p*p;
t/=2;
}
long long ans=(11*d.v[0][0]+2*d.v[1][0])%mod;
(ans=ans+mod-5)%=mod;
ans=ans*ksm(6,mod-2,mod)%mod;
printf("%lld\n",ans);
}
}
本文探讨了一个复杂的数学构造题,通过巧妙的构造和矩阵快速幂优化,解决了递推式中的难题。详细解析了如何从特征方程出发,利用韦达定理和循环节理论,最终高效求解特定项的值。
202

被折叠的 条评论
为什么被折叠?



