1. 程式人生 > >HDOJ 4549 M斐波那契數列 費馬小定理+矩陣快速冪

HDOJ 4549 M斐波那契數列 費馬小定理+矩陣快速冪

MF( i ) = a ^ fib( i-1 ) * b ^ fib ( i )   ( i>=3)

mod 1000000007 是質數 , 根據費馬小定理  a^phi( p ) = 1 ( mod p )  這裡 p 為質數 且 a 比 p小 所以 a^( p - 1 ) = 1 ( mod p )

所以對很大的指數可以化簡  a ^ k % p  == a ^ ( k %(p-1) ) % p

用矩陣快速冪求fib數後代入即可

M斐波那契數列

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 1672    Accepted Submission(s): 482


Problem Description M斐波那契數列F[n]是一種整數數列,它的定義如下:

F[0] = a
F[1] = b
F[n] = F[n-1] * F[n-2] ( n > 1 )

現在給出a, b, n,你能求出F[n]的值嗎?
Input 輸入包含多組測試資料;
每組資料佔一行,包含3個整數a, b, n( 0 <= a, b, n <= 10^9 )
Output 對每組測試資料請輸出一個整數F[n],由於F[n]可能很大,你只需輸出F[n]對1000000007取模後的值即可,每組資料輸出一行。
Sample Input 0 1 0 6 10 2
Sample Output 0 60
Source
/* ***********************************************
Author        :CKboss
Created Time  :2015年03月12日 星期四 22時44分35秒
File Name     :HDOJ4549.cpp
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>

using namespace std;

typedef long long int LL;

const LL mod=1000000007LL;
const LL md=1000000006LL;

/// getfib
LL a,b,n;

struct Matrix
{
	Matrix(LL a=0,LL b=0,LL c=0,LL d=0)
	{
		m[0][0]=a; m[0][1]=b;
		m[1][0]=c; m[1][1]=d;
	}
	LL m[2][2];
};

Matrix MUI(Matrix& a,Matrix& b)
{
	Matrix ret;
	ret.m[0][0]=((a.m[0][0]*b.m[0][0])%md+(a.m[0][1]*b.m[1][0])%md)%md;
	ret.m[0][1]=((a.m[0][0]*b.m[0][1])%md+(a.m[0][1]*b.m[1][1])%md)%md;
	ret.m[1][0]=((a.m[1][0]*b.m[0][0])%md+(a.m[1][1]*b.m[1][0])%md)%md;
	ret.m[1][1]=((a.m[1][0]*b.m[0][1])%md+(a.m[1][1]*b.m[1][1])%md)%md;
	return ret;
}

Matrix QUICKPOW(LL m)
{
	Matrix E(1,0,0,1);
	Matrix A(1,1,1,0);
	while(m)
	{
		if(m&1LL) E=MUI(E,A);
		A=MUI(A,A);
		m/=2LL;
	}
	return E;
}

void showMat(Matrix M)
{
	cout<<endl;
	for(int i=0;i<2;i++)
	{
		for(int j=0;j<2;j++)
			cout<<M.m[i][j]<<",";
		cout<<endl;
	}
	cout<<endl;
}

/// get p_th fib number
LL getfib(LL p) 
{
	p--;
	Matrix M1=QUICKPOW(p);
	return M1.m[0][0];
}

LL QUICKPOW2(LL a,LL x)
{
	LL e=1LL;
	while(x)
	{
		if(x&1LL) e=(e*a)%mod;
		a=(a*a)%mod;
		x/=2LL;
	}
	return e;
}

LL solve()
{
	if(n==0) return a;
	else if(n==1) return b;
	else if(n==2) return (a*b)%mod;

	///a的fib係數 -> fib(n-1)
	LL xa = getfib(n-1);
	LL partA = QUICKPOW2(a,xa);

	///b的fib係數 -> fib(i)
	LL xb = getfib(n);
	LL partB = QUICKPOW2(b,xb);

	return (partA*partB)%mod;
}

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);

	while(cin>>a>>b>>n)
		cout<<solve()<<endl;
    
    return 0;
}