zoukankan      html  css  js  c++  java
  • HDU 4549 M斐波那契数列(矩阵快速幂)

    题目链接:M斐波那契数列

    题意:$F[0]=a,F[1]=b,F[n]=F[n-1]*F[n-2]$。给定$a,b,n$,求$F[n]$。

    题解:暴力打表后发现$ F[n]=a^{fib(n-1)} * b^{fib(n)} $

    斐波那契数列可用矩阵快速幂求解。但是此题中n较大,fib会爆掉。这时候需要引入费马小定理优化。

    证明:$a^x \% p = a^{x \%(p-1)} \%p$

    1. $a^x \% p = a^{x \% (p-1) + x/(p-1)*(p-1)} \% p$

    2. $a^x \% p = a^{x \% (p-1)} * a^{x/(p-1)*(p-1)} \%p$

    3. $a^{x/(p-1)*(p-1)} \% p= ({a^{p-1}}) ^ {(x/(p-1))} \%p = 1^ {(x/(p-1))}$

    把3式带入2式,即可证明。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #define N 2
     6 using namespace std;
     7 
     8 typedef long long ll;
     9 const ll mod=1000000007;
    10 
    11 struct mat
    12 {
    13     ll m[N][N]=
    14     {
    15      {1,1},
    16      {1,0}
    17     };
    18 };
    19 
    20 mat mul(mat a,mat b,ll p)
    21 {
    22     mat ans;
    23     int i,j,k;
    24     for(i=0;i<N;i++)
    25     for(j=0;j<N;j++)
    26     ans.m[i][j]=0;
    27 
    28     for(i=0;i<N;i++)
    29     for(j=0;j<N;j++)
    30     for(k=0;k<N;k++)
    31     ans.m[i][j]=(ans.m[i][j]+a.m[i][k]*b.m[k][j])%p;
    32     return ans;
    33 }
    34 
    35 ll matpow(ll n,ll p)
    36 {
    37     if(n<0) return 0;
    38     mat ans,tmp;
    39     int i,j;
    40     for(int i=0;i<N;i++)
    41     for(int j=0;j<N;j++)
    42     ans.m[i][j]=0;
    43 
    44     ans.m[0][0]=0;
    45     ans.m[1][0]=1;
    46     while(n)
    47     {
    48         if(n&1) ans=mul(tmp,ans,p);
    49         tmp=mul(tmp,tmp,p);
    50         n=n>>1;
    51     }
    52     return ans.m[0][0]%p;
    53 }
    54 
    55 ll fast_mod(ll a,ll b,ll p){
    56     ll res=1;
    57     while(b){
    58         if(b&1) res=(res*a)%p;
    59         a=(a*a)%p;
    60         b>>=1;
    61     }
    62     return res;
    63 }
    64 
    65 int main(){
    66     ll n,a,b;
    67 
    68     while(scanf("%lld%lld%lld",&a,&b,&n)!=EOF){
    69         if(n==0){
    70             printf("%lld
    ",a);
    71             continue;
    72         }
    73         else if(n==1){
    74             printf("%lld
    ",b);
    75             continue;
    76         }
    77         else if(a==0||b==0){
    78             printf("0
    ");
    79             continue;
    80         }
    81         ll m1=matpow(n-1,mod-1);
    82         ll m2=matpow(n,mod-1);
    83         ll ans=(fast_mod(a,m1,mod)*fast_mod(b,m2,mod))%mod;
    84         printf("%lld
    ",ans%mod);
    85     }
    86 
    87     return 0;
    88 }
    View Code
  • 相关阅读:
    实现LNMP
    iptabes的用法
    实现LAMP
    实现https
    硬盘信息和磁盘分区管理
    awk
    【BZOJ 2288】 2288: 【POJ Challenge】生日礼物 (贪心+优先队列+双向链表)
    【BZOJ 1150】 1150: [CTSC2007]数据备份Backup (贪心+优先队列+双向链表)
    【BZOJ 1216】 1216: [HNOI2003]操作系统 (模拟+优先队列)
    【BZOJ 1528】 1528: [POI2005]sam-Toy Cars (贪心+堆)
  • 原文地址:https://www.cnblogs.com/pavtlly/p/9811333.html
Copyright © 2011-2022 走看看