NYIST OJ 1000 又見Fibonacci數列

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章