首页 > 代码库 > HDU2855—Fibonacci Check-up
HDU2855—Fibonacci Check-up
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2855
题目意思:求一个式子g[n]=∑C(n,k)*f[k],n很大,很明显是一个矩阵快速幂。可以打表发现g[n]=f[2*n]划开可以发现g[n]=3*g[n-1]-f[n-2]。
思路:我们现在可以证明一下
f[2*n]=f[2*n-1]+f[2*n-2];
其中f[2*n-1]=f[2*n-2]+f[2*n-3]
f[2*n-2]=f[2*n-3]+f[2*n-4]
所以f[2*n]=f[2*n-2]+f[2*n-3]+f[2*n-3]+f[2*n-4]=2*f[2*n-2]+f[2*n-3]=2*f[2*n-2]+f[2*n-3]+f[2*n-4]-f[2*n-4]=3*f[2*n-2]-f[2*n-4]。我们化简一下g[n]=3*g[n-1]-g[n-2]。我们可以通过打表得到这个结论。
现在我们可以从数学上证明一下这个结论。
方法:1.通项公式:f[n]=(1/sqrt(5))*(((1+sqrt(5))/2)^n-((1-sqrt(5))/2)^n)
2.二项式:(1+a)^n=∑(C(n,k)*a^k)(0<=k<=n)
∑C(n,k)*f[k]=(1/sqrt(5))*∑C(n,k)*(((1+sqrt(5))/2)^k-((1-sqrt(5))/2)^k)
=(1/sqrt(5))*(∑C(n,k)*((1+sqrt(5))/2)^k-∑C(n,k)*((1-sqrt(5))/2)^k)
=(1/sqrt(5))*((3+sqrt(5))/2)^n-((3-sqrt(5))/2)^n)
=(1/sqrt(5))*((1+sqrt(5))/2)^(2*n)-((1-sqrt(5))/2)^(2*n))
=f[2*n]
这个组合数的应用感觉十分有意思。
代码:
//Author: xiaowuga #include<bits/stdc++.h> #define maxx INT_MAX #define minn INT_MIN #define inf 0x3f3f3f3f #define N 2 using namespace std; long long MOD; typedef long long ll; ll n,size=2;//第n项,矩阵大小 struct Matrix{ ll mat[N][N]; void clear(){ memset(mat,0,sizeof(mat)); } Matrix operator * (const Matrix & m) const{ Matrix tmp; int i ,j,k; tmp.clear(); for( i=0;i<size;i++) for( k=0;k<size;k++){ if(mat[i][k]==0) continue; for( j=0;j<size;j++){ tmp.mat[i][j]+=mat[i][k]*m.mat[k][j]%MOD; tmp.mat[i][j]%=MOD; } } return tmp; } }; Matrix POW(Matrix m,ll k){ Matrix ans; memset(ans.mat,0,sizeof(ans.mat)); for(int i=0;i<size;i++) ans.mat[i][i]=1; while(k){ if(k&1) ans=ans*m; k/=2; m=m*m; } return ans; } int main() { Matrix m; m.clear(); m.mat[0][0]=3;m.mat[0][1]=-1; m.mat[1][0]=1;m.mat[1][1]=0; int T; cin>>T; for(int i=0;i<T;i++){ cin>>n>>MOD; if(n==0) {cout<<0<<endl;continue;} Matrix ans=POW(m,n-1); ll sum=(ans.mat[0][0]%MOD+MOD)%MOD; cout<<sum<<endl; } return 0; }
HDU2855—Fibonacci Check-up