M斐波那契数列 HDU - 4549

M斐波那契数列 HDU - 4549
思路:题意很简单,但是不好写,如果不知道幂的取模的话,基本就是tle。要知道如下定理:当m为素数,且a、m互质时, a^n % m = a^(n%(m-1)) % m。取模的问题解决了,就是矩阵快速幂了。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const ll mod=1000000007;
struct  matrix{
    ll x[2][2];
};
ll a1,b1,n;
//有如下定理:当m为素数,且a、m互质时, a^n % m = a^(n%(m-1)) % m。
ll gcd(ll a,ll b)
{
    return b==0?a:gcd(b,a%b);
}
matrix multi(matrix a,matrix b){
    matrix temp;
    memset(temp.x,0,sizeof(temp.x));
    for(int i=0;i<2;i++)
        for(int j=0;j<2;j++)
            for(int k=0;k<2;k++)
            {
                temp.x[i][j]+=(a.x[i][k]*b.x[k][j])%(mod-1);
                //if(gcd(temp.x[i][j],a1)==1) temp.x[i][j]%=(mod-1);
                temp.x[i][j]%=(mod-1);
            }
    return temp;
}

matrix quick_multi(matrix a,ll m)//矩阵快速幂
{
    matrix temp=a;
    m--;
    while(m){
        if(m&1)
            temp=multi(temp,a);//
        a=multi(a,a);
        m>>=1;
    }
    return temp;
}
ll quic_power(ll x,ll n)
{
    ll result=1;
    while(n)
    {
        if(n&1)
        {
            result*=x;
            result%=mod;
        }
        x*=x;
        x%=mod;
        n>>=1;
    }
    return result;
}
int main()
{
    while(scanf("%lld%lld%lld",&a1,&b1,&n)!=EOF)
    {
        matrix A,B;
        memset(A.x,0,sizeof(A.x));
        memset(B.x,0,sizeof(B.x));
        B.x[0][0]=A.x[0][0]=A.x[0][1]=A.x[1][0]=1;
        if(n<=1) n==0?printf("%lld\n",a1%mod):printf("%lld\n",b1%mod);
        else
        {
            A=quick_multi(A,n-1);
            B=multi(A,B);
            //printf("%lld %lld\n",B.x[0][0],B.x[1][0]);
            a1=quic_power(a1,B.x[1][0])%mod;
            b1=quic_power(b1,B.x[0][0])%mod;
            printf("%lld\n",(a1*b1)%mod);
        }

    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Miranda_ymz/article/details/81698792