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

4549 】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]的值嗎?
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; }