4549 】M斐波那契數列 【矩陣快速冪+費馬小定理降冪】
阿新 • • 發佈:2019-02-02
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
分析: 先寫出幾項根據題意
0 a
1 b
2 a*b
3 a*b^2
4 a^2*b^3
5 a^3*b^5
….
規律很明顯,除去前兩項,從第三項開始關於a的冪的增長規律1 1 2 3 5 ….. 關於b的冪增長規律1 2 3 5 …. ,可以看到冪的增長呈斐波那契數列,b比a快一項。
最後的答案格式為 a ^ x * b ^ y %mod
n為1e9 這樣到最後,第n項的x和y都是天數了,根本無法求。
所以這裡用到了費馬小定理降冪,因為mod>a mod>b,同時mod為素數,所以gcd(a,mod)==1,gcd(b,mod)==1條件滿足,可以使用
我們可以先求a ^ x %mod 再求 b ^ y %mod
a=a ^ ( x % (mod-1 ) ) %mod ,b=b ^ ( y %(mod-1)) %mod
ans = a * b % mod ;
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int>pii;
#define first fi
#define second se
#define LL long long
#define fread() freopen("in.txt","r",stdin)
#define fwrite() freopen("out.txt","w",stdout)
#define CLOSE() ios_base::sync_with_stdio(false)
const int MAXN = 1e5 ;
const int MAXM = 1e6;
const int mod = 1e9+7 - 1 ; //
const int inf = 0x3f3f3f3f;
struct Matrix{
LL a[5][5];
int h,w;
}ori,res,it;
void init(){
it.w=2,it.h=1;it.a[1][1]=1,it.a[1][2]=1;
memset(res.a,0,sizeof(res.a));
res.a[1][1]=res.a[2][2]=1;res.w=res.h=2;
memset(ori.a,0,sizeof (ori.a));
ori.w=ori.h=2;
ori.a[1][1]=ori.a[1][2]=ori.a[2][1]=1;
}
Matrix mutil(Matrix a, Matrix b ){
Matrix c;memset(c.a,0,sizeof(c.a));
c.h=a.h,c.w=b.w;
for(int i=1;i<=a.h;i++){
for(int k=1;k<=a.w;k++){
if(a.a[i][k]==0 ) continue;
for(int j=1;j<=b.w;j++)
c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j]%mod)%mod;
}
}
return c;
}
void Matrix_mod(int n){
// if(n<=1) return 1;
n-=2;
while(n){
if(n&1) res=mutil(ori,res);
ori=mutil(ori,ori);
n>>=1;
}
res=mutil(it,res);
}
LL power(LL a,LL b,LL c){
LL s=1,base=a%c;
while(b){
if(b&1) s=s*base%c;
base=base*base%c;
b>>=1;
}
return s;
}
int main(){
CLOSE();
// fread();
// fwrite();
LL a,b,n;
while(scanf("%lld%lld%lld",&a,&b,&n)!=EOF){
init();
if(n==0) printf("%lld\n",a);
else if(n==1) printf("%lld\n",b);
else {
Matrix_mod(n);
LL c=power(a,res.a[1][2],mod+1);
LL d=power(b,res.a[1][1],mod+1);
//printf("%d%d\n",res.a[1][2],res.a[1][1]);
printf("%lld\n",(c*d)%(mod+1));
}
}
return 0;
}