题目链接:M斐波那契数列
题意:$F[0]=a,F[1]=b,F[n]=F[n-1]*F[n-2]$。给定$a,b,n$,求$F[n]$。
题解:暴力打表后发现$ F[n]=a^{fib(n-1)} * b^{fib(n)} $
斐波那契数列可用矩阵快速幂求解。但是此题中n较大,fib会爆掉。这时候需要引入费马小定理优化。
证明:$a^x \% p = a^{x \%(p-1)} \%p$
1. $a^x \% p = a^{x \% (p-1) + x/(p-1)*(p-1)} \% p$
2. $a^x \% p = a^{x \% (p-1)} * a^{x/(p-1)*(p-1)} \%p$
3. $a^{x/(p-1)*(p-1)} \% p= ({a^{p-1}}) ^ {(x/(p-1))} \%p = 1^ {(x/(p-1))}$
把3式带入2式,即可证明。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #define N 2 6 using namespace std; 7 8 typedef long long ll; 9 const ll mod=1000000007; 10 11 struct mat 12 { 13 ll m[N][N]= 14 { 15 {1,1}, 16 {1,0} 17 }; 18 }; 19 20 mat mul(mat a,mat b,ll p) 21 { 22 mat ans; 23 int i,j,k; 24 for(i=0;i<N;i++) 25 for(j=0;j<N;j++) 26 ans.m[i][j]=0; 27 28 for(i=0;i<N;i++) 29 for(j=0;j<N;j++) 30 for(k=0;k<N;k++) 31 ans.m[i][j]=(ans.m[i][j]+a.m[i][k]*b.m[k][j])%p; 32 return ans; 33 } 34 35 ll matpow(ll n,ll p) 36 { 37 if(n<0) return 0; 38 mat ans,tmp; 39 int i,j; 40 for(int i=0;i<N;i++) 41 for(int j=0;j<N;j++) 42 ans.m[i][j]=0; 43 44 ans.m[0][0]=0; 45 ans.m[1][0]=1; 46 while(n) 47 { 48 if(n&1) ans=mul(tmp,ans,p); 49 tmp=mul(tmp,tmp,p); 50 n=n>>1; 51 } 52 return ans.m[0][0]%p; 53 } 54 55 ll fast_mod(ll a,ll b,ll p){ 56 ll res=1; 57 while(b){ 58 if(b&1) res=(res*a)%p; 59 a=(a*a)%p; 60 b>>=1; 61 } 62 return res; 63 } 64 65 int main(){ 66 ll n,a,b; 67 68 while(scanf("%lld%lld%lld",&a,&b,&n)!=EOF){ 69 if(n==0){ 70 printf("%lld ",a); 71 continue; 72 } 73 else if(n==1){ 74 printf("%lld ",b); 75 continue; 76 } 77 else if(a==0||b==0){ 78 printf("0 "); 79 continue; 80 } 81 ll m1=matpow(n-1,mod-1); 82 ll m2=matpow(n,mod-1); 83 ll ans=(fast_mod(a,m1,mod)*fast_mod(b,m2,mod))%mod; 84 printf("%lld ",ans%mod); 85 } 86 87 return 0; 88 }