矩阵快速幂,欧拉定理,二分幂模板,乘法二分模板 hdu 4549

M斐波那契数列

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


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
 

 

Source
解题思路:经过对f[n]通项公式推倒,可以得出F(n)=a^f(n)*b^f(n-1);
其中f[n]为斐波那契数列,由于幂次很大,因此可以根据欧拉定理对指数进行处理,然后先二分快速幂,在乘法快速取模就可以得出答案。
ac代码:
#include<iostream>
#include<stdio.h>
using namespace std;
typedef __int64 ll;
struct Matrix
{
    ll a[2][2];
    void init()
    {
        a[0][0] = a[1][0] = a[0][1] = 1;
        a[1][1] = 0;
    }
};
Matrix matrix_mul(Matrix a, Matrix b)
{
    int i, j, k;
    Matrix ans;
    for(i = 0; i < 2; i++)
    {
        for(j = 0; j < 2; j++)
        {
            ans.a[i][j] = 0;
            for(k = 0; k < 2; k++)
                ans.a[i][j] += a.a[i][k] * b.a[k][j];
            ans.a[i][j] %= 1000000006;
        }
    }
    return ans;
}
ll mul(ll a,ll b,ll c)
{
       ll ans=0;
       while(b)
       {
              if(b&1)ans=(ans+a)%c;
              a=(a<<1)%c;
              b>>=1;
       }
       return ans;
}
ll pow(ll a,ll b,ll c)
{
       ll ans=1;
       while(b)
       {
              if(b&1)ans=mul(ans,a,c);
              a=mul(a,a,c);
              b>>=1;
       }
       return ans;
}
Matrix mult(Matrix a, ll b) 
{

Matrix ans; ans.init();

while(b)
{

if
(b & 1)
ans = matrix_mul(ans, a);

b >>= 1;
a = matrix_mul(a, a);
}

return
ans;
}

int
main()
{

ll n ,aa,bb;
while
(~scanf("%I64d%I64d%I64d", &aa,&bb,&n))
{

if
(n==0) { printf("%I64d\n",aa); continue; }
if
(n==1) { printf("%I64d\n",bb); continue; }

Matrix ans1,ans2, tmp; tmp.init();
ans1 = mult(tmp, n); tmp.init();
ans2 = mult(tmp, n-1);
ll p=ans1.a[1][1]%1000000007;
ll q=ans2.a[1][1]%1000000007;
ll i=pow(aa,q,1000000007);
ll j=pow(bb,p,1000000007);
ll m=mul(i,j,1000000007);
printf("%I64d\n",m);
}

return
0;
}
 
posted @ 2013-05-26 03:25  线性无关  阅读(246)  评论(0)    收藏  举报