官方题解:
观察递推式我们可以发现,所有的fi都是a的幂次,所以我们可以对fi取一个以a为底的log,gi=loga fi
那么递推式变gi=b+c∗gi−1+gi−2,这个式子可以矩阵乘法
这题有一个小trick,注意a mod p=0的情况.
分析:排除了a mod p=0的情况,幂次可以对(p-1)取模,这是由于离散对数定理
相关定理请查阅 算导
吐槽:比赛的时候就是被a mod p=0这种情况给hack掉了,我太弱了
#include <stdio.h> #include <iostream> #include <vector> #include <math.h> #include <set> #include <map> #include <queue> #include <algorithm> #include <string.h> #include <string> using namespace std; typedef long long LL; const int INF=0x3f3f3f3f; const int N=1e5+5; LL p,a,b,c,n; struct asd{ LL c[4][4]; }; asd mul(asd a,asd b){ asd d; for(int i=1;i<=3;++i){ for(int j=1;j<=3;++j){ d.c[i][j]=0; for(int k=1;k<=3;++k) d.c[i][j]=(d.c[i][j]+a.c[i][k]*b.c[k][j]%(p-1))%(p-1); } } return d; } asd fun(LL m){ asd a,e; for(int i=1;i<=3;++i) for(int j=1;j<=3;++j) a.c[i][j]=e.c[i][j]=0; a.c[1][1]=c; a.c[1][2]=1; a.c[1][3]=b; a.c[2][1]=1; a.c[3][3]=1; e.c[1][1]=e.c[2][2]=e.c[3][3]=1; while(m){ if(m&1)e=mul(e,a); m>>=1; a=mul(a,a); } return e; } LL fun2(LL a,LL x){ LL res=1; while(x){ if(x&1)res=(res*a)%p; x>>=1; a=(a*a)%p; } return res; } int main() { int T; scanf("%d",&T); while(T--){ scanf("%I64d%I64d%I64d%I64d%I64d",&n,&a,&b,&c,&p); if(n==1){ printf("1 "); continue; } if(n==2){ printf("%I64d ",fun2(a,b)); continue; } if(a%p==0){ printf("0 "); continue; } asd t=fun(n-2); LL x=0; x=(x+t.c[1][1]*b%(p-1))%(p-1); x=(x+t.c[1][3])%(p-1); printf("%I64d ",fun2(a,x)); } return 0; }