zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    守卫者的挑战
    黑魔法师之门
    noip2015 普及组
    noip2015 提高组day1、day2
    40026118素数的个数
    高精度模板
    经典背包系列问题
    修篱笆
    [LintCode] Linked List Cycle
    [LintCode] Merge Two Sorted Lists
  • 原文地址:https://www.cnblogs.com/orion7/p/8318454.html
Copyright © 2011-2022 走看看