HDU 4291 A Short problem [矩阵]

  求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 //}
posted @ 2012-09-20 07:18  Burn_E  阅读(160)  评论(0)    收藏  举报