HDU 4549 M斐波那契数列(矩阵快速幂 费马小定理)

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

题意

题解

由于n很大,所以直接递推不行。观察F[n]的后几项发现a,b的次数是满足斐波那契数列的,(1,1,2,3, 5,8...)。然后计算aF[n-1]*bF[n]就行了,题目要求F[n]对1000000007取模,这里用费马小定理
即: 假如p是质数,且gcd(a,p)=1,那么 a(p-1)≡1(mod p),即:假如a是整数,p是质数,且a,p互质(即两者只有一个公约数1),那么a的(p-1)次方除以p的余数恒等于1 (来自百度百科)

所以:ap %mod = ap%(mod-1)%mod

最后需要注意n为0,1的时候。

代码

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int mod=1000000007;
typedef long long LL;
struct Matrix
{
    LL a[2][2];
    Matrix()
    {
        memset(a,0,sizeof(a));
    }
    void init()
    {
        for(int i=0;i<2;i++)
            a[i][i]=1;
    }
    Matrix operator *(const Matrix &B)
    {
        Matrix C;
        for(int i=0;i<2;i++)
            for(int k=0;k<2;k++)
                for(int j=0;j<2;j++)
                    C.a[i][j]=(C.a[i][j]+a[i][k]*B.a[k][j])%(mod-1);
        return  C;
    }
    Matrix operator ^(int n)
    {
        Matrix res,A=(*this);
        res.init();
        while(n)
        {
            if(n&1)
                res=res*A;
            A=A*A;
            n>>=1;
        }
        return res;
    }
};
LL quick_pow(int a,LL b)
{
    LL ans=1;
    LL tmp=1LL*a;
    while(b)
    {
        if(b&1)
            ans=(ans*tmp)%mod;
        tmp=(tmp*tmp)%mod;
        b>>=1;
    }
    return ans;
}
int main()
{
    int a,b,n;
    while(cin>>a>>b>>n)
    {
        if(n==0)
        {
            cout<<a<<endl;
            continue;
        }
        else if(n==1)
        {
            cout<<b<<endl;
            continue;
        }
        Matrix A;
        A.a[0][0]=A.a[0][1]=A.a[1][0]=1;
        A.a[1][1]=0;
        A=A^(n-2);
        LL ans=(quick_pow(a,A.a[1][0]+A.a[1][1])*quick_pow(b,A.a[0][0]+A.a[0][1]))%mod;
        cout<<ans<<endl;
    }
    return 0;
}