M斐波那契数列
(使用费马小定理降幂处理以及矩阵的快速幂求法)
M斐波那契数列F[n]是一种整数数列,它定义如下:
F[0] = a
F[1] = b
F[n] = F[n-1] * F[n-2] (n>1)
现在,写出F[2]、F[3]、F[4]的值,可以发现,其中,a,b的指数均为斐波那契数,归纳法得 :
F[n] = a^Fib[n-1] *b^Fib[n]
费马小定理:
A^B%C = A^(B%(C-1))%C (C是质数,且A、C互质)
所以 F[n] = (a^(Fib[n-1]%(C-1)%C) * (b^(Fib[n]%(C-1))%C)
而对于斐波那契数列 Fib[n] = Fib[n-1] + Fib[n-2] 是一个二阶递推数列,所以存在一个2*2的矩阵A,使得 :
(FnFn−1)=(Fn−1Fn−2)∗A
求解,A得到:
[1110]
Input:
a、b、n
Output:
F[n],若F[n]过大,输出F[n]对1000000007取模
#include <stdio.h>
const long long M=1000000007;
class Matrix
{
public:
int m[2][2];
// 2*2的矩阵相乘
Matrix mul(Matrix x){
Matrix ans;
ans.m[0][0] = (m[0][0]*x.m[0][0]+m[0][1]*x.m[1][0])%(M-1);
ans.m[0][1] = (m[0][0]*x.m[0][1]+m[0][1]*x.m[1][1])%(M-1);
ans.m[1][0] = (m[1][0]*x.m[0][0]+m[1][1]*x.m[1][0])%(M-1);
ans.m[1][1] = (m[1][0]*x.m[0][1]+m[1][1]*x.m[1][1])%(M-1);
return ans;
}
//设为单位矩阵
void SetIdentity(){
m[0][0] = 1;
m[1][1] = 1;
m[0][1] = 0;
m[1][0] = 0;
}
//设为2*2矩阵A
/**
* [ 1 1 ]
* [ 1 0 ]
*/
void SetDefault(){
m[0][0] = 1;
m[0][1] = 1;
m[1][0] = 1;
m[1][1] = 0;
}
};
Matrix Fib(int n){
Matrix A,ans;
A.SetDefault();
ans.SetIdentity();
// 矩阵快速幂
while(n){
if( n&1 )
ans = ans.mul(A);
A = A.mul(A);
n >>= 1;
}
return ans;
}
long long quickpow(long long x,long long y){
long long res = 1;
while(y){
if(y&1) res = res*x % M;
y >>=1;
x = x*x%M;
}
return res;
}
int main(){
long long a,b,n;
while(~scanf("%lld%lld%lld",&a,&b,&n)){
Matrix f = Fib(n);
long long answer;
answer = quickpow(a,f.m[1][1])*quickpow(b,f.m[1][0])%M;
printf("%lld\n",answer);
}
return 0;
}