Problem Description
According to a research, VIM users tend to have shorter fingers, compared with Emacs users.
Hence they prefer problems short, too. Here is a short one:
Given n (1 <= n <= 1018), You should solve for
g(g(g(n))) mod 109 + 7
where
g(n) = 3g(n - 1) + g(n - 2)
g(1) = 1
g(0) = 0
Hence they prefer problems short, too. Here is a short one:
Given n (1 <= n <= 1018), You should solve for
where
Input
There are several test cases. For each test case there is an integer n in a single line.
Please process until EOF (End Of File).
Please process until EOF (End Of File).
Output
For each test case, please print a single line with a integer, the corresponding answer to this case.
Sample Input
0
1
2
Sample Output
0
1
42837
这题主要找循环节,mo1=1000000007,mo2=222222224,mo3=183120;找到循环节后只要用矩阵快速幂就可以了,下面有找循环节代码。
由于找循环节很耗时,所以找到后直接写出来,不用写在代码里。
找循环节:
1 #include<cstdio> 2 long long mo1=1000000007; 3 int main() 4 { 5 long long i=1,a=1,b=0,c; 6 while (i) 7 { 8 c=(3*a+b)%mo1; 9 b=a; 10 a=c; 11 if (a==1&&b==0) 12 { 13 printf("%I64d\n",i); 14 break; 15 } 16 i++; 17 } 18 }
ac代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 long long mo1=1000000007; 6 long long mo2=222222224; 7 long long mo3=183120; 8 long long s1[3][3],s2[3][3],s3[3][3]; 9 long long f(long long n,long long mo) 10 { 11 int i,j,k; 12 s1[0][0]=s2[0][0]=3; 13 s1[0][1]=s2[0][1]=1; 14 s1[1][0]=s2[1][0]=1; 15 s1[1][1]=s2[1][1]=0; 16 n-=2; 17 while (n) 18 { 19 if (n&1) 20 { 21 memset(s3,0,sizeof(s3)); 22 for (k=0;k<2;k++) 23 for (i=0;i<2;i++){if (!s1[i][k]) continue; 24 for (j=0;j<2;j++) 25 s3[i][j]=(s3[i][j]+s1[i][k]*s2[k][j])%mo;} 26 for (i=0;i<2;i++) 27 for (j=0;j<2;j++) s2[i][j]=s3[i][j]; 28 } 29 memset(s3,0,sizeof(s3)); 30 for (k=0;k<2;k++) 31 for (i=0;i<2;i++) {if (!s1[i][k]) continue; 32 for (j=0;j<2;j++) 33 s3[i][j]=(s3[i][j]+s1[i][k]*s1[k][j])%mo;} 34 for (i=0;i<2;i++) 35 for (j=0;j<2;j++) s1[i][j]=s3[i][j]; 36 n>>=1; 37 } 38 return s2[0][0]; 39 } 40 int main() 41 { 42 long long n; 43 long long ans; 44 while (~scanf("%I64d",&n)) 45 { 46 if (n==0) {printf("0\n");continue;} 47 if (n==1) {printf("1\n");continue;} 48 ans=f(n,mo3); 49 if (ans>=2) //一定要有,不然ans<2时函数就会死循环。 50 ans=f(ans,mo2); 51 if (ans>=2) 52 ans=f(ans,mo1); 53 printf("%I64d\n",ans); 54 } 55 }