• NYOJ 1000


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

    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
    ",a%MOD);
    63              continue;         
    64         }         
    65         else if(n==1) { 
    66             printf("%lld
    ",b%MOD);
    67              continue;         
    68         }
    69          else if(n==2) { 
    70             printf("%lld
    ",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
    ",ans);         
    79         }     
    80     }     
    81 
    82     return 0;
    83 } 
  • 相关阅读:
    chromedriver安装与配置(ubuntu linux下)
    Ajax 通信技术--hidden Frame GET 请求 和 POST 请求
    photoshop去除图片上的水印
    redis和memcache的对比
    关于mongodb ,redis,memcache之间见不乱理还乱的关系和作用
    MYSQL中'TYPE=MyISAM'错误的解决方案
    http协议
    jQuery常用方法
    SQL Server中行列转换 Pivot UnPivot
    jQuery插件开发
  • 原文地址:https://www.cnblogs.com/liugl7/p/6274723.html
Copyright © 2020-2023  润新知