hdu 4549 欧拉定理+各种快速幂

与hdu 3221类似......不想多说

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#define MOD 1000000007

using namespace std;

typedef long long LL;

struct mat 
{
    LL m[3][3];
    mat ( )
    {
        memset ( m , 0 , sizeof ( m ) );
    }
};

mat multi ( mat a , mat b , LL mod )
{
    mat c;
    for ( LL i = 1 ; i < 3 ; i++ )
        for ( LL j = 1 ; j < 3 ; j++ )
            if ( a.m[i][j] )
                for ( LL k = 1 ; k < 3 ; k++ )
                    c.m[i][k] = (c.m[i][k] + a.m[i][j]*b.m[j][k]%mod )%mod;
    return c;    
}

mat quickMulti ( mat a , LL n , LL mod )
{
    mat ans;
    for ( int i = 1 ; i < 3 ; i++ ) ans.m[i][i] = 1;
    while ( n )
    {
        if ( n&1 ) ans = multi ( ans , a , mod  );
        a = multi ( a , a , mod );
        n >>= 1;
    }
    return ans;
}

LL pow ( LL num , LL n )
{
    LL ans = 1;
    while ( n )
    {
        if ( n&1 ) ans = ans * num % MOD;
        num = num*num%MOD;
        n >>= 1;
    }
    return ans;
}

LL euler ( LL x )
{
    LL res = x;
    for ( int i = 2 ; i*i<=x ; i++ )
    {
        if ( x%i ) continue;
        res -= res/i;
        while ( x%i==0 ) x /= 1;
    } 
    if ( x > 1 ) res -= res/x;
    return res;
}

LL index ( LL n  , LL mod )
{
    LL  a = 1 , b = 0 ,temp , i ;
    for ( i = 1 ; i <= n ; i++ )
    {
        temp = a + b;
        b = a;
        a = temp;
        if ( a >= mod ) break;
    }
    if ( i > n ) return a;
    mat ma ,mb;
    ma.m[1][1] = mb.m[1][1] = mb.m[2][1] = mb.m[1][2]=1;
    mb = quickMulti ( mb , n , mod );
    ma = multi ( ma , mb , mod );
    return ma.m[1][1]%mod + mod;
}

int main ( )
{
    LL phi = euler ( MOD );
    LL a,b,n;
    while ( ~scanf ( "%lld%lld%lld" , &a , &b , &n ) )
    {
        if ( n == 0 )
        {
            printf ( "%lld\n" , a%MOD );
            continue;
        }
        if ( n == 1 )
        {
            printf ( "%lld\n" , b%MOD );
            continue;
        }
        if ( a == 0 || b == 0 )
        {
            printf ( "0\n" );
            continue;
        }
        LL ans = pow ( a , index(n-2 , phi ))*pow( b , index ( n-1 , phi ))%MOD; 
        printf ( "%lld\n" , ans );
    }
}


你可能感兴趣的:(hdu 4549 欧拉定理+各种快速幂)