版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011815404/article/details/88879546
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 2Sample Output
0
60
思路:
根据 F[0]=a,F[1]=b 与 F[n] = F[n-1] * F[n-2] 进行递推
有:
其中,f[i] 为斐波那契数列数列,即:f[i]=f[i-1]+f[i-2]
因此,可先根据斐波那契数列构造矩阵,求出 f[n-1] 与 f[n],然后直接求 F[n]
构造矩阵,有:
化简,得:
那么:
由于 n 最大可达到 1E9,f[n] 与 f[n-1] 会很大,要求的 一定会爆
因此要使用费马小定理降幂
根据费马小定理:
那么:
Source Program
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define PI acos(-1.0)
#define E 1e-9
#define INF 0x3f3f3f3f
#define LL long long
const int MOD=1000000007;
const int N=10+5;
const int dx[]= {-1,1,0,0};
const int dy[]= {0,0,-1,1};
using namespace std;
struct Matrix{
LL s[N][N];
};
Matrix e;//单位矩阵E
Matrix x;//构造矩阵
void init(){
for(int i=1;i<=2;i++)//主对角线为1
e.s[i][i]=1;
}
Matrix mul(Matrix A,Matrix B,LL n){//矩阵乘法,n代表A、B两个矩阵是n阶方阵
Matrix temp;//临时矩阵,存放A*B结果
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
temp.s[i][j]=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
temp.s[i][j]=(temp.s[i][j]+A.s[i][k]*B.s[k][j])%(MOD-1);//费马小定理降幂后模为1E9-1
return temp;
}
Matrix quickPower(Matrix a,LL b,LL n){//矩阵快速幂,求矩阵n阶矩阵的b次幂
Matrix ans=e;
while(b){
if(b&1)
ans=mul(ans,a,n);//ans=e*a
a=mul(a,a,n);//a=a*a
b>>=1;
}
return ans;
}
LL quickPow(LL a,LL b){//快速幂
LL res=1;
while(b){
if(b&1)
res=(res*a)%MOD;
a=(a*a)%MOD;
b>>=1;
}
return res;
}
int main(){
init();
LL a,b,n;
while(scanf("%lld%lld%lld",&a,&b,&n)!=EOF){
LL fa;//a的幂
LL fb;//b的幂
if(n==0){
fa=1;
fb=0;
}
else if(n==1){
fa=0;
fb=1;
}
else if(n==2){
fa=1;
fb=1;
}
else{
x.s[1][1]=1;x.s[1][2]=1;
x.s[2][1]=1;x.s[2][2]=0;
Matrix res=quickPower(x,n-2,2);
//注意MOD降幂
fa=((res.s[2][1]+res.s[2][2])%(MOD-1)+(MOD-1))%(MOD-1);//fn-1
fb=((res.s[1][1]+res.s[1][2])%(MOD-1)+(MOD-1))%(MOD-1);//fn
}
LL temp1=quickPow(a,fa);//a^f(n-1)
LL temp2=quickPow(b,fb);//b^f(n)
LL result=(temp1*temp2)%MOD;
printf("%lld\n",result);
}
return 0;
}