求g(g(g(n))) mod 109 + 7,已知g(n) = 3g(n - 1) + g(n - 2),g(1) = 1,g(0) = 0。
因为每两个数只和前两个数有关,所以模之后必然会出现循环节。现在只知道最外层的循环节,所以要把内两层的循环节暴力出来。有了三层的循环节之后用二分矩阵就可以了。
1 #include <string.h> 2 #include <stdio.h> 3 typedef long long LL; 4 struct matrix{ 5 LL mz[2][2]; 6 void init(int type){ 7 memset(mz,0,sizeof mz); 8 if(type==1)mz[0][0]=mz[1][1]=1; 9 if(type==2)mz[0][0]=3,mz[1][0]=mz[0][1]=1; 10 } 11 }; 12 int mod; 13 matrix operator *(matrix a,matrix b){ 14 matrix ans;ans.init(0); 15 ans.mz[0][0]=(a.mz[0][0]*b.mz[0][0]+a.mz[0][1]*b.mz[1][0])%mod; 16 ans.mz[0][1]=(a.mz[0][0]*b.mz[0][1]+a.mz[0][1]*b.mz[1][1])%mod; 17 ans.mz[1][0]=(a.mz[1][0]*b.mz[0][0]+a.mz[1][1]*b.mz[1][0])%mod; 18 ans.mz[1][1]=(a.mz[1][0]*b.mz[0][1]+a.mz[1][1]*b.mz[1][1])%mod; 19 return ans; 20 } 21 LL binmat(LL x,int mmod){ 22 matrix tmp;tmp.init(2); 23 matrix ans;ans.init(1); 24 mod=mmod; 25 for(;x;x>>=1,tmp=tmp*tmp) 26 if(x&1)ans=ans*tmp; 27 return ans.mz[0][1]; 28 } 29 LL n; 30 int main(){ 31 //getcircle(1000000007,0); 32 while(scanf("%I64d",&n)!=EOF){ 33 LL ans=binmat(binmat(binmat(n,183120),222222224),1000000007); 34 printf("%I64d\n",ans); 35 } 36 return 0; 37 } 38 //void getcircle(int mod,int step){ 39 // if(step==2)return; 40 // int g1=0,g2=1,x=0,tmp; 41 // while(1){ 42 // x++,tmp=g2,g2=((LL)g2*3+g1)%mod,g1=tmp; 43 // if(g2==1&&g1==0)break; 44 // } 45 // printf("%d\n",x); 46 // getcircle(x,step+1); 47 //}