M斐波那契数列(HDU-4549)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011815404/article/details/88879546

Problem Description

M斐波那契数列F[n]是一种整数数列,它的定义如下: 

F[0] = a 
F[1] = b 
F[n] = F[n-1] * F[n-2] ( n > 1 ) 

现在给出a, b, n,你能求出F[n]的值吗?

Input

输入包含多组测试数据; 
每组数据占一行,包含3个整数a, b, n( 0 <= a, b, n <= 10^9 )

Output

对每组测试数据请输出一个整数F[n],由于F[n]可能很大,你只需输出F[n]对1000000007取模后的值即可,每组数据输出一行。

Sample Input

0 1 0
6 10 2

Sample Output

0
60

思路:

根据 F[0]=a,F[1]=b 与 F[n] = F[n-1] * F[n-2] 进行递推

有:

\begin{matrix}F[2]=ab \\ F[3]=ab^2 \\ F[4]=a^2b^3 \\ F[5]=a^3b^5 \\ F[6]=a^5b^8 \\ F[7]=a^8b^{13} \\ ... \\ F[n]=a^{f(n-1)}b^{f(n)} \end{matrix}

扫描二维码关注公众号,回复: 5735699 查看本文章

其中,f[i] 为斐波那契数列数列,即:f[i]=f[i-1]+f[i-2]

因此,可先根据斐波那契数列构造矩阵,求出 f[n-1] 与 f[n],然后直接求 F[n]

构造矩阵,有:\begin{bmatrix} f(n) \\ f(n-1) \end{bmatrix}=\begin{bmatrix} 1 &1 \\ 1&0 \end{bmatrix} \begin{bmatrix} f(n-1) \\ f(n-2) \end{bmatrix}

化简,得:\begin{bmatrix} f(n) \\ f(n-1) \end{bmatrix}=\begin{bmatrix} 1 &1 \\ 1&0 \end{bmatrix}^{n-2} \begin{bmatrix} f(1) \\ f(0) \end{bmatrix}=\begin{bmatrix} 1 &1 \\ 1&0 \end{bmatrix}^{n-2} \begin{bmatrix} 1 \\ 1 \end{bmatrix}

那么:f(n)=A[1][1]+A[1][2],f(n-1)=A[2][1]+A[2][2]

由于 n 最大可达到 1E9,f[n] 与 f[n-1] 会很大,要求的 F[n]=(a^{f(n-1)}\:mod \:m)(b^{f(n)}\:mod \:m) 一定会爆

因此要使用费马小定理降幂

根据费马小定理:a^p\:mod\:m\equiv a^{p\:mod\:(m-1)}

那么:F(n)=a^{f(n-1)\:mod\:(m-1)}b^{f(n)\:mod\:(m-1)}

Source Program

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define PI acos(-1.0)
#define E 1e-9
#define INF 0x3f3f3f3f
#define LL long long
const int MOD=1000000007;
const int N=10+5;
const int dx[]= {-1,1,0,0};
const int dy[]= {0,0,-1,1};
using namespace std;
struct Matrix{
    LL s[N][N];
};
Matrix e;//单位矩阵E
Matrix x;//构造矩阵

void init(){
    for(int i=1;i<=2;i++)//主对角线为1
        e.s[i][i]=1;
}
Matrix mul(Matrix A,Matrix B,LL n){//矩阵乘法,n代表A、B两个矩阵是n阶方阵
    Matrix temp;//临时矩阵,存放A*B结果

    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            temp.s[i][j]=0;

    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            for(int k=1;k<=n;k++)
                temp.s[i][j]=(temp.s[i][j]+A.s[i][k]*B.s[k][j])%(MOD-1);//费马小定理降幂后模为1E9-1
    return temp;
}
Matrix quickPower(Matrix a,LL b,LL n){//矩阵快速幂,求矩阵n阶矩阵的b次幂
    Matrix ans=e;
    while(b){
        if(b&1)
            ans=mul(ans,a,n);//ans=e*a
        a=mul(a,a,n);//a=a*a
        b>>=1;
    }
    return ans;
}
LL quickPow(LL a,LL b){//快速幂
    LL res=1;
    while(b){
        if(b&1)
            res=(res*a)%MOD;
        a=(a*a)%MOD;
        b>>=1;
    }
    return res;
}
int main(){
    init();
    LL a,b,n;
    while(scanf("%lld%lld%lld",&a,&b,&n)!=EOF){
        LL fa;//a的幂
        LL fb;//b的幂
        if(n==0){
            fa=1;
            fb=0;
        }
        else if(n==1){
            fa=0;
            fb=1;
        }
        else if(n==2){
            fa=1;
            fb=1;
        }
        else{
            x.s[1][1]=1;x.s[1][2]=1;
            x.s[2][1]=1;x.s[2][2]=0;

            Matrix res=quickPower(x,n-2,2);
            //注意MOD降幂
            fa=((res.s[2][1]+res.s[2][2])%(MOD-1)+(MOD-1))%(MOD-1);//fn-1
            fb=((res.s[1][1]+res.s[1][2])%(MOD-1)+(MOD-1))%(MOD-1);//fn
        }

        LL temp1=quickPow(a,fa);//a^f(n-1)
        LL temp2=quickPow(b,fb);//b^f(n)

        LL result=(temp1*temp2)%MOD;

        printf("%lld\n",result);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/u011815404/article/details/88879546