hdu4549M斐波那契数列 矩阵快速幂 + 费马小定理

//f[0] = a ;
//f[1] = b ;
//f[n] = f[n-1]*f[n-2]  n>=2
//给a , b , n 
//求f[n]
//可以很容易得到
//f[n] = a^(F[n-1])*b^(F[n-2]) n>=2
//用矩阵快速幂很容易求F[n]
//注意F[n]会很大
//所以可以根据费马小定理可以在求的时候F[n]%=(mod-1)
#include
#include
#include
using namespace std ;
const int maxn = 10 ;
typedef long long ll ;
const ll mod = 1000000007 ;
int n  = 2  ;
struct node
{
    ll p[maxn][maxn] ;
};
ll pow(ll a , ll k)
{
    ll c = 1 ;
    while(k)
    {
        if(k&1)c = (c*a)%mod ;
        a = (a*a)%mod ;
        k >>= 1 ;
    }
    return c%mod ;
}
node mul(node a , node b)
{
    node c ;
    memset(c.p , 0 , sizeof(c.p)) ;
    for(int i = 1;i <= n;i++)
      for(int j = 1;j <= n;j++)
        for(int k = 1;k <= n;k++)
        c.p[i][j] = (c.p[i][j] + a.p[i][k]*b.p[k][j])%(mod-1) ;
    return c ;
}
node powa(node a , ll k)
{
    node c ;
    memset(c.p , 0 , sizeof(c.p)) ;
    for(int i = 1;i <= n;i++)
    c.p[i][i] = 1 ;
    while(k)
    {
        if(k&1)
          c = mul(c, a) ;
        a = mul(a , a) ;
        k >>= 1 ;
    }
    return c ;
}

int main()
{
  // freopen("in.txt" , "r" , stdin ) ;
    ll a , b , k;
    node c ;
    c.p[1][1] = (ll)0 ;
    c.p[1][2] = c.p[2][1] = c.p[2][2] = (ll)1 ;
    while(~scanf("%lld%lld%lld" , &a , &b , &k))
    {
        if(k == 0)
        {
            printf("%lld\n" , a) ;
            continue ;
        }
        if(k == 1)
        {
            printf("%lld\n" , b) ;
            continue ;
        }
        node an = powa(c , k-1) ;
        ll f2 = an.p[2][2] ;
        ll f1 = an.p[1][2] ;
        ll ans = (pow(a , f1)*pow(b , f2))%mod ;
        printf("%lld\n" , ans) ;
    }
}

你可能感兴趣的:(矩阵快速幂,数论)