題目鏈接: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>