链接:
Description:
定义一种新型的Fibonacii 数列:
F[0] = a
F[1] = b
F[i] = F[i-1] * F[i-2] (n > 1)
请根据给出的a,b,n,求出F[n]的大小。
Input:
多组测试数据,处理到文件结束,对于每组测试数据:
输入三个整数a,b,n(0≤a,b,n≤10^9)
Output:对于每组测试数据输出F[n]对1000000007取模后的结果,每组输出占一行;
分析:
矩阵乘法+数论
因为F[n] = F[n-1] * F[n-2]
设f(0) = 0, f(1) = 1, f(n) = f(n-1) + f(n-2) (n>=2)
那么有 F(n) = a^f(n) * b^f(n+1)
根据费马小定理,1000000007是一个素数,那么所求可以简化成 a^(f(n)%1000000006) * b^(f(n+1)%1000000006)
所以我们可以先求f(n)%1000000006和f(n+1)%1000000006 , 可用快速幂来求得;
同样再用快速幂求的 a^(f(n)%1000000006) 和 b^(f(n+1)%1000000006)即可;
解题代码如下:
#include <cstdio>
#include <cstring>
#include <ctime>
#include <algorithm>
using namespace std;
const long long mod = 1000000007;
const long long mod2 = 1000000006;
void mul(long long a[][2], long long b[][2], long long m){
long long c[2][2];
int i, j, k;
for (i=0; i<2; i++){
for (j=0; j<2; j++){
c[i][j] = 0;
for (k=0; k<2; k++){
c[i][j] += (a[i][k] * b[k][j])%m;
}
}
}
for (i=0; i<2; i++)
for (j=0; j<2; j++){
b[i][j] = c[i][j]%m;
}
}
long long cal(long long n){
long long e[2][2], r[2][2];
e[0][0] = e[0][1] = e[1][0] = 1; e[1][1] = 0;
r[0][0] = 1; r[1][0] = 0;
n--;
while (n){
if (n%2==1)
mul(e, r, mod2);
mul(e, e, mod2);
n = n/2;
}
return r[0][0];
}
long long solve(long long a, long long b){
long long res = 1;
while (b){
if (b%2==1)
res = (res * a)%mod;
a = (a*a)%mod;
b /= 2;
}
return res;
}
int main(){
long long a, b, n;
long long k1, k2, res;
while (scanf("%lld %lld %lld",&a,&b,&n)!=EOF){
if (n==0){ printf("%lld\n",a%mod); continue;}
if (n==1){ printf("%lld\n",b%mod); continue;}
if (n==2){ printf("%lld\n",(a*b)%mod); continue;}
k1 = cal(n-1);
k2 = cal(n);
k1 = solve(a, k1);
k2 = solve(b, k2);
printf("%lld\n",(k1*k2)%mod);
}
}