矩阵快速幂,欧拉定理,二分幂模板,乘法二分模板 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]的值吗?
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 )
每组数据占一行,包含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;
}

浙公网安备 33010602011771号