• 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 } 
  • 相关阅读:
    IDEA插件和快捷设置
    漫谈虚拟内存
    漫谈进程和线程
    漫谈计算机语言
    初识Python
    数据库物理设计
    漫谈计算机体系
    数据库逻辑设计
    NLP中几种分词库的简单使用(Python)
    ML————朴素贝叶斯原理和SKlearn相关库
  • 原文地址:https://www.cnblogs.com/liugl7/p/6274723.html
Copyright © 2020-2023  润新知