题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=1000
描述 斐波那契数列大家应该很熟悉了吧。下面给大家引入一种新的斐波那契数列:M斐波那契数列。 M斐波那契数列F[n]是一种整数数列,它的定义如下:
F[0] = a
F[1] = b
F[n] = F[n-1] * F[n-2] ( n > 1 )
现在给出a, b, n,聪明的你能求出F[n]的值吗?
-
输入
-
输入包含多组测试数据;
每组数据占一行,包含3个整数a, b, n( 0 <= a, b, n <= 10^9 )
输出
- 对每组测试数据请输出一个整数F[n],由于F[n]可能很大,你只需输出F[n]对1000000007取模后的值即可,每组数据输出一行。 样例输入
-
0 1 0 6 10 2
样例输出
-
0 60
计算发现F(2)= a * b,F(3)= a * (b^2),F(4)= (a^2) * (b^3),F(5)= (a^3) * (b^5)...
显然F(n)中a的次数是真正fibonacci中第i-1项,b的次数是真正fibonacci中第i项。所以,先求出fibonacci中第n-1项和第n项,设为x,y,则F(n)= (a^x) * (b ^y)。在求值的时候要注意使用Fermat小定理,避免x、y溢出。
代码如下所示:
<span style="font-size:14px;">#include <iostream>
#include <algorithm>
using namespace std;
#ifdef _MSC_VER
typedef __int64 lld;
#else
typedef long long lld;
#endif
const lld MOD = 1000000007;
const lld PMOD = 1000000006;//phi(MOD)
lld a, b, n;
lld fa, fb;
struct Matrix{
union{
struct{
lld _00, _01;
lld _10, _11;
};
lld ele[4];
};
};
Matrix Identity;
bool Handle();
int main(){
Identity._00 = 0, Identity._01 = 1, Identity._10 = 1, Identity._11 = 1;
while (Handle()){
//empty while
}
}
Matrix GetFibonacci(int k);//return kth fibonacci
Matrix operator * (const Matrix& lhs, const Matrix& rhs);
lld QuickPow(lld base, lld exp, lld mod);
bool Handle(){
if (!(cin >> a >> b >> n)){
return false;
}
if (n == 1){
cout<<b % MOD<<endl;
return true;
} else if (n == 0){
cout<<a% MOD<<endl;
return true;
} else if (!a || !b){
cout<<0<<endl;
return true;
}
//we must caculate it
const Matrix& mat = GetFibonacci(n-1);
lld x = QuickPow(a, mat._01, MOD), y = QuickPow(b, mat._11, MOD);
cout<< (x* y ) % MOD<<endl;
return true;
}
Matrix operator * (const Matrix& lhs, const Matrix& rhs){
Matrix result;
result._00 = lhs._00 * rhs._00 + lhs._01 * rhs._10;
result._01 = lhs._00 * rhs._01 + lhs._01 * rhs._11;
result._10 = lhs._10 * rhs._00 + lhs._11 * rhs._10;
result._11 = lhs._10 * rhs._01 + lhs._11 * rhs._11;
return result;
}
Matrix GetFibonacci(int k){//return kth fibonacci
Matrix mat;
if (k == 1){
return Identity;
} else{
mat = GetFibonacci(k>>1);
mat = mat * mat;
for (int i = 0; i < 4; ++i){
mat.ele[i] %= PMOD;
}
if (k & 1){
mat = mat * Identity;
for (int i = 0; i < 4; ++i){
mat.ele[i] %= PMOD;
}
}
return mat;
}
}
lld QuickPow(lld base, lld exp, lld mod){//(base^exp) % mod
if (exp == 1){
return base % mod;
} else if (exp == 0){
return 1;
}
lld x = QuickPow(base, exp>>1, mod);
x *= x;
x %= mod;
if (exp & 1){
x *= base;
x %= mod;
}
return x;
}</span>