码迷,mamicode.com
首页 > 其他好文 > 详细

NYOJ 1000

时间:2017-01-12 08:55:32      阅读:253      评论:0      收藏:0      [点我收藏+]

标签:amp   使用   src   mat   ima   实现   main   迭代   tin   

整体的思路是“快速幂取模算法”和“矩阵快速幂算法”的结合

F[0] = a1b0

F[1] = a0b1

F[2] = a1b1

F[3] = a1b2

F[4] = a2b3

F[5] = a3b5

F[6] = a5b8

...

观察可知F[n] = af(n-2)·bf(n-1)其中f(n-1)、f(n-2)是斐波那契数列,设p=1000000007(经检验可知p是质数,这引导我们中间计算矩阵幂时可用费马小定理)

故问题可转化为求  af(n-2)·bf(n-1)%p,即 (af(n-2)%p)·(bf(n-1)%p)%p.  接下来用快速幂取模算法解决,详见 http://www.cnblogs.com/liugl7/p/4831030.html

在使用快速幂取模算法之前需要解决的问题是快速计算斐波那契数列的值的问题,传统的迭代算法并不能满足快速计算的需求,所以这里使用矩阵快速幂算法。

令:

    技术分享        技术分享        技术分享

则易得  Mn  = M0Fn   (n>=1)

所以只需要计算出Fn然后乘上M0即可得到Mn, 然后就可以得到f(n-1),f(n-2)代入  (af(n-2)%p)·(bf(n-1)%p)%p 的计算。

 

代码如下:

 1 #include <iostream> 
 2 #include <cstdio>  
 3 using namespace std;  
 4 typedef long long LL; 
 5 #define MOD 1000000007  
 6 
 7 struct Matrax {     //定义2*2的矩阵 
 8     LL mat[2][2]; 
 9 }U,F;  
10 
11 //2*2的两矩阵的乘法 
12 Matrax multi(Matrax a,Matrax b) {
13     Matrax ans;     
14     int i,j,k;     
15     for(i=0;i<2;i++) {         
16         for(j=0;j<2;j++) {             
17             ans.mat[i][j]=0;             
18             for(k=0;k<2;k++)     
19                 ans.mat[i][j]=(ans.mat[i][j]+(a.mat[i][k]%(MOD-1))*(b.mat[k][j]%(MOD-1)))%(MOD-1); 
20          }      
21     }         
22     return ans;  
23 }  
24 
25 //实现矩阵p的n次方   
26 Matrax my_pow_matrax(int n) {     
27     Matrax p=F,ans=U;     
28     while(n) {         
29         if(n&1) ans=multi(ans,p);
30                  
31         n>>=1;         
32         p=multi(p,p);     
33     }     
34     return ans; 
35 }  
36 
37 //初始化矩阵U=[1,0;0,1],即二阶单位矩阵;  F=[1,1;1,0] 
38 void Init() {     
39     U.mat[0][0]=U.mat[1][1]=1;     
40     U.mat[0][1]=U.mat[1][0]=0;          
41     F.mat[0][0]=F.mat[0][1]=F.mat[1][0]=1;     
42     F.mat[1][1]=0; 
43 }  
44 
45 //快速幂取模算法,可用来得到  a^f(n-2)%p  和  b^f(n-1)%p   
46 LL my_pow_ll(LL a,LL n) {     
47     LL ans=1ll,p=a;     
48     while(n)     {         
49         if(n&1)             
50             ans=((ans%MOD)*(p%MOD))%MOD;         
51         n>>=1;         
52         p=((p%MOD)*(p%MOD))%MOD;      
53     }     
54     return ans; 
55 }  
56 
57 int main() {     
58     Init();     
59     LL a,b,n;     
60     while(scanf("%lld%lld%lld",&a,&b,&n)!=EOF) { 
61         if(n==0) {             
62             printf("%lld\n",a%MOD);
63              continue;         
64         }         
65         else if(n==1) { 
66             printf("%lld\n",b%MOD);
67              continue;         
68         }
69          else if(n==2) { 
70             printf("%lld\n",a*b%MOD);
71              continue;         
72         }
73          else         {             
74              Matrax temp=my_pow_matrax(n-1);
75              LL f1=temp.mat[0][0]*1+temp.mat[1][0]*0; // fib(n-1)
76              LL f2=temp.mat[0][1]*1+temp.mat[1][1]*0;  // fib(n-2)
77              LL ans=(my_pow_ll(a,f2)%MOD)*(my_pow_ll(b,f1)%MOD)%MOD;
78              printf("%lld\n",ans);         
79         }     
80     }     
81 
82     return 0;
83 } 

 

NYOJ 1000

标签:amp   使用   src   mat   ima   实现   main   迭代   tin   

原文地址:http://www.cnblogs.com/liugl7/p/6274723.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!