HDU4291—A Short problem

Posted xiaowuga

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU4291—A Short problem相关的知识,希望对你有一定的参考价值。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4291

题目意思:求g(g(g(n))) mod 109 + 7,其中g(n) = 3g(n - 1) + g(n - 2),g(1) = 1,g(0) = 0。

思路:一个很简单的矩阵快速幂,简单的想法就是先用n算出g(n),然后再算g(g(n)),然后再算最外层,都是mod(1e9+7),这么做就错了,这道题有一个循环节的问题,看来这种嵌套的递推式取mod是存在循环节的,以后要注意下。

计算循环节的代码(貌似方法叫做弗洛伊德判圈法?):

 1 #include <cstdio>  
 2 #include <iostream>  
 3 using namespace std;  
 4 #define LL __int64  
 5 LL mod=1e9+7;  
 7 int main()  
 8 {  
 9     LL i,a,b,g;  
10     a=1,b=0;  
11     for(i=1;;i++)  
12     {  
13         g=(3*a+b)%mod;  
14         b=a;  
15         a=g;  
16         if(a==1&&b==0)  
17         {  
18             if(i!=mod) {mod=i;}  
19             else break;
20             cout<<i<<endl;  
21             i=1;
22         }         
23     }  
24     return 0;  
25 }  

代码:

技术分享
 1 #include<cstdio>  
 2 #include<cstring>  
 3 #include<iostream>  
 4 #include<algorithm>  
 5 using namespace std;  
 6   
 7 typedef __int64 int64;  
 8 const int N = 2;  
 9   
10 int64 n;  
11 struct Matrix{  
12     int64 mat[N][N];  
13     int64 MOD;  
14     Matrix operator*(const Matrix& m)const{  
15           Matrix tmp;  
16           tmp.MOD = MOD;  
17           for(int i = 0 ; i < N ; i++){  
18               for(int j = 0 ; j < N ; j++){  
19                   tmp.mat[i][j] = 0;  
20                   for(int k = 0; k < N ; k++)  
21                       tmp.mat[i][j] += mat[i][k]*m.mat[k][j]%MOD;  
22                   tmp.mat[i][j] %= MOD;  
23               }  
24           }  
25           return tmp;  
26     }  
27 };  
28   
29 int64 Pow(Matrix m , int64 x , int64 MOD){  
30     if(x <= 1) return x;  
31     Matrix ans;  
32     ans.MOD = m.MOD = MOD;  
33     ans.mat[0][0] = ans.mat[1][1] = 1;  
34     ans.mat[1][0] = ans.mat[0][1] = 0;  
35     x--;  
36     while(x){  
37         if(x%2)  
38             ans = ans*m;  
39         x /= 2;  
40         m = m*m;  
41     }  
42     return ans.mat[0][0]%MOD;  
43 }  
44   
45 // 暴力找到循环节  
46 int64 getLoop(int64 MOD){  
47     int64 pre1 = 1;  
48     int64 pre2 = 0;  
49     for(int64 i = 2 ; ; i++){  
50         int64 x = 3*pre1%MOD+pre2%MOD;  
51         x %= MOD;  
52         // update  
53         pre2 = pre1;  
54         pre1 = x;  
55         int64 y = 3*pre1%MOD+pre2%MOD;  
56         if(x == 0 && y == 1){  
57             return i;  
58         }   
59     }  
60 }  
61   
62 int main(){  
63     int64 L1 = 1e9+7;   
64     int64 L2 = 222222224;  
65     int64 L3 = 183120;  
66     Matrix m;  
67     m.mat[0][0] = 3; m.mat[1][1] = 0;  
68     m.mat[0][1] = 1; m.mat[1][0] = 1;  
69     while(scanf("%I64d" , &n) != EOF){  
70          int64 x = Pow(m , n , L3);  
71          int64 y = Pow(m , x , L2);  
72          int64 ans = Pow(m , y , L1);  
73          printf("%I64d\n" , ans);  
74     }  
75     return 0;  
76 }  
View Code

 

以上是关于HDU4291—A Short problem的主要内容,如果未能解决你的问题,请参考以下文章

HDU - 4291 循环节

hdu 4291 矩阵幂 循环节

hdu 1402 A * B Problem Plus(FFT)

hdu 1402 A * B Problem Plus(FFT)

hdu 1402 A * B Problem Plus(FFT)

HDU 1695 GCD 莫比乌斯反演例题