hdu4549 矩阵快速幂 + 欧拉降幂

R - M斐波那契数列
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u
Appoint description: 

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
 
 
列出数列的前几项可以观察得到,每一项的a,b的值满足f[i] = f[i-1] + f[i-2],所以能够用矩阵构造。 但是我们的答案最后要取mod,矩阵里的值可能也会超过long long,
所以也需要降幂,此时可以用欧拉降幂,如果有公式a^x (mod m),并且gcd(x,m)==1,即x和m互质,那么a^x = a^(x % Eular(m));由于m是质数,所以Eular(m) = m - 1;
最后再快速幂、相乘(要取模)即可;
 
#include<map>
#include<set>
#include<string>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<cstdio>
#include<time.h>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 1000000001
#define ll long long
#define MOD 1000000007
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int MAXN = 100010;
struct Mat
{
    ll a[2][2];
};
ll fa,fb,n;
Mat operator *(Mat a,Mat b)
{
    Mat c;
    memset(c.a,0,sizeof(c.a));
    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] += (a.a[i][k] * b.a[k][j])%(MOD-1);
            }
        }
    }
    return c;
}
Mat power(Mat b,ll n)
{
    Mat c;
    c.a[0][0] = c.a[1][1] = 1;
    c.a[0][1] = c.a[1][0] = 0;
    while(n){
        if(n & 1){
            c = c * b;
        }
        b = b * b;
        n >>= 1;
    }
    return c;
}
ll mod_pow(ll x,ll n)
{
    ll res = 1;
    while(n){
        if(n & 1) res = res * x % MOD;
        x = x * x % MOD;
        n >>= 1;
    }
    return res;
}
ll mod_mul(ll a,ll b)
{
    ll res = 0;
    while(b){
        if(b & 1){
            res = (res + a) % MOD;
        }
        b >>= 1;
        a = (a + a) % MOD;
    }
    return res;
}
int main()
{
    while(~scanf("%lld%lld%lld",&fa,&fb,&n)){
        if(fa == 0 || fb == 0){
            cout<<0<<endl;
            continue;
        }
        if(n == 0){
            cout<<fa%MOD<<endl;
            continue;
        }
        else if(n == 1){
            cout<<fb%MOD<<endl;
            continue;
        }
        Mat a;
        a.a[0][0] = 0;
        a.a[0][1] = a.a[1][0] = a.a[1][1] = 1;
        a = power(a,n-2);
        ll num1 = (a.a[0][0] + a.a[0][1])%(MOD-1);
        ll num2 = (a.a[1][0] + a.a[1][1])%(MOD-1);
        ll ans1 = mod_pow(fa,num1);
        ll ans2 = mod_pow(fb,num2);
        ll ans = mod_mul(ans1,ans2);
        printf("%lld\n",ans);
    }
    return 0;
}

 

posted @ 2016-04-26 20:24  sweat123  阅读(371)  评论(0编辑  收藏  举报