题目链接: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 " , ans); 74 } 75 return 0; 76 }