hdu 4291 2012成都赛区网络赛 矩阵快速幂 ***

分析:假设g(g(g(n)))=g(x),x可能非常大,但是由于mod 10^9+7,所以可以求出x的循环节

求出x的循环节后,假设g(g(g(n)))=g(x)=g(g(y)),即x=g(y),y也可能非常大,但是由x的循环节可以求出y的循环节

所以最终结果只要进行矩阵快速幂即可求出

循环节

 1 #include<stdio.h>
 2 
 3 const long long MOD=222222224;//第一次是MOD=1000000007 找出循环节是222222224
 4 //第二次是MOD=222222224,找出循环节183120
 5 int main()
 6 {
 7     long long a,b;
 8     a=1;
 9     b=3;
10     for(int i=1;;i++)
11     {
12         if(a==0&&b==1)
13         {
14             printf("%d\n",i);
15             break;
16         }
17         long long c=3*b+a;
18         c%=MOD;
19         a=b;
20         b=c;
21     }
22     return 0;
23 }

 

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<string>
 6 #include<queue>
 7 #include<algorithm>
 8 #include<map>
 9 #include<iomanip>
10 #define INF 99999999
11 using namespace std;
12 
13 const int mod1=1000000007;//求结果的循环节 
14 const int mod2=222222224;//第1层的循环节,假设g(g(g(n)))=g(x),即mod2是x的循环节 
15 const int mod3=183120;//第2层的循环节假设g(g(g(n)))=g(g(y)),即mod3是y的循化节 
16 
17 __int64 array[2][2],sum[2][2];
18 
19 void MatrixMult(__int64 a[2][2],__int64 b[2][2],int mod){
20     __int64 c[2][2]={0};
21     for(int i=0;i<2;++i){
22         for(int j=0;j<2;++j){
23             for(int k=0;k<2;++k){
24                 c[i][j]+=a[i][k]*b[k][j];
25             }
26         }
27     }
28     for(int i=0;i<2;++i){
29         for(int j=0;j<2;++j)a[i][j]=c[i][j]%mod;
30     }
31 }
32 
33 __int64 Matrix(__int64 k,int mod){
34     array[0][0]=3,array[1][1]=0;
35     array[0][1]=array[1][0]=1;
36     sum[0][0]=sum[1][1]=1;
37     sum[0][1]=sum[1][0]=0;
38     while(k){
39         if(k&1)MatrixMult(sum,array,mod);
40         MatrixMult(array,array,mod);
41         k>>=1;
42     }
43     return sum[0][0];
44 }
45 
46 int main(){
47     /*__int64 a=0,b=1;
48     for(int i=2;;++i){//求循环节 
49         a=(b*3+a)%mod2;
50         a=a^b;
51         b=a^b;
52         a=a^b;
53         if(a == 0 && b == 1){cout<<i-1<<endl;break;}//i-1=222222224
54     }*/
55     __int64 n;
56     while(scanf("%I64d",&n)!=EOF){
57         if(n>=2)n=Matrix(n-1,mod3);
58         if(n>=2)n=Matrix(n-1,mod2);
59         if(n>=2)n=Matrix(n-1,mod1);
60         printf("%I64d\n",n);
61     }
62     return 0;
63 }

 

转载于:https://www.cnblogs.com/cnblogs321114287/p/4745292.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值