• hdu4549 M-fib数列 费马小定理+矩阵快速幂


    hdu4549 M-fib数列   费马小定理+矩阵快速幂

    M斐波那契数列

    Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
    Total Submission(s): 2122    Accepted Submission(s): 606


    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(n)=a^fib(n-2) * b^fib(n-1) %p。
    由于幂太大,所以就用费马小定理。。。
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    
    using namespace std;
    
    const int maxn=1000100;
    const int INF=(1<<29);
    typedef unsigned long long ll;
    const ll p=1000000007;
    ll a,b,n;
    struct Matrix
    {
        ll a[2][2];
        friend Matrix operator*(Matrix A,Matrix B)
        {
            Matrix C={0,0,0,0};
            for(int i=0;i<2;i++){
                for(int j=0;j<2;j++){
                    for(int k=0;k<2;k++){
                        C.a[i][j]=(C.a[i][j]%(p-1)+((A.a[i][k]%(p-1))*(B.a[k][j]%(p-1)))%(p-1))%(p-1);
                    }
                }
            }
            return C;
        }
    };
    
    Matrix qpow_M(Matrix n,ll k)
    {
        Matrix res={1,0,0,1};
        while(k){
            if(k&1) res=res*n;
            n=n*n;
            k>>=1;
        }
        return res;
    }
    
    ll fib(ll n)
    {
        Matrix tmp={1,1,1,0};
        Matrix res=qpow_M(tmp,n);
        return res.a[0][0];
    }
    
    ll qpow(ll n,ll k,ll p)
    {
        ll res=1;
        while(k){
            if(k&1) res=((res%p)*(n%p))%p;
            n=((n%p)*(n%p))%p;
            k>>=1;
        }
        return res;
    }
    
    ll solve(ll a,ll n)
    {
        ll k=fib(n);
        return qpow(a,k,p);
    }
    
    ll F(ll n)
    {
        ll A=solve(a,n-2);
        ll B=solve(b,n-1);
        return(A*B)%p;
    }
    
    int main()
    {
        while(~scanf("%I64d%I64d%I64d",&a,&b,&n)){
            if(a==0){
                printf("%I64d
    ",n==1?b:0);
                continue;
            }
            if(b==0){
                printf("%I64d
    ",n?0:a);
                continue;
            }
            if(n>=2) printf("%I64d
    ",F(n));
            else printf("%I64d
    ",n?b:a);
        }
        return 0;
    }
    View Code
    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    006 date find
    005 输出重定向 > >>命令 echo命令 tail命令
    总结,一周,
    mokey 学习
    树状,
    定制,
    萌芽,
    到底为什么,
    会,
    “恋爱”,一路走来,
  • 原文地址:https://www.cnblogs.com/--560/p/4753159.html
Copyright © 2020-2023  润新知