题目链接:https://ac.nowcoder.com/acm/contest/3002/J
题意:给出一个递推式: f[i]=f[i-2] * f[i-1] * ab。并且 f[1] = x , f[2] = y , 其中x,y,a,b<=1e12,求第n项f[n]。(n<=1e12)
思路:
首先列出前几项的表达式如下:
我们可以发现根据递推式发现,x的系数:fx(i) = fx(i-2) +fx(i-1),y的系数:fy(i) = fy(i-2) +fy(i-1),a的系数:fa(i) = fa(i-2) +fa(i-1)+b。于是可以用矩阵快速幂来求系数。然后根据费马小定理知道矩阵快速幂过程中的模数MODD=1e9+6。
AC代码:
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int MOD=1e9+7; const int MODD=1e9+6; typedef long long LL; LL n,x,y,a,b; int up; struct Mat{ LL m[5][5]; Mat(){memset(m,0,sizeof(m));} }; LL qpow(LL a,LL b){ LL ret=1; a%=MOD; while(b){ if(b&1) ret=ret*a%MOD; a=a*a%MOD; b>>=1; } return ret; } Mat Matmul(Mat a,Mat b){ Mat ret; for(int i=1;i<=up;++i) for(int j=1;j<=up;++j) for(int k=1;k<=up;++k){ ret.m[i][j]+=a.m[i][k]*b.m[k][j]%MODD; ret.m[i][j]%=MODD; } return ret; } Mat Matqpow(Mat a,LL b){ Mat ret; for(int i=1;i<=up;++i) ret.m[i][i]=1; while(b){ if(b&1) ret=Matmul(ret,a); a=Matmul(a,a); b>>=1; } return ret; } int main(){ scanf("%lld%lld%lld%lld%lld",&n,&x,&y,&a,&b); x%=MOD,y%=MOD,a%=MOD,b%=MOD-1; if(n==1){ printf("%lld ",x); return 0; } else if(n==2){ printf("%lld ",y); return 0; } else if(x==0||y==0||a==0){ printf("0 "); return 0; } else{ up=2; Mat mx1,mx2; mx1.m[1][1]=mx1.m[1][2]=mx1.m[2][1]=1; mx2.m[2][1]=1; mx1=Matqpow(mx1,n-2); mx1=Matmul(mx1,mx2); LL res1=qpow(x,mx1.m[1][1]); Mat my1,my2; my1.m[1][1]=my1.m[1][2]=my1.m[2][1]=1; my2.m[1][1]=1; my1=Matqpow(my1,n-2); my1=Matmul(my1,my2); LL res2=qpow(y,my1.m[1][1]); up=3; Mat ma1,ma2; ma1.m[1][1]=ma1.m[1][2]=ma1.m[1][3]=ma1.m[2][1]=ma1.m[3][3]=1; ma2.m[3][1]=b; ma1=Matqpow(ma1,n-2); ma1=Matmul(ma1,ma2); LL res3=qpow(a,ma1.m[1][1]); LL ans=res1*res2%MOD*res3%MOD; printf("%lld ",ans); } return 0; }