CSU 1208: Fibonacci sum
题目链接:http://122.207.68.93/OnlineJudge/problem.php?id=1208
比赛的时候只是觉得是矩阵,但是一直没想到怎么推...(a+b)^k应该联想到二项式的啊ToT,而且他说k<=20,明摆着就是告诉你可以矩阵的...正确的构造方法是:
C(k,0) c(k-1,0) C(k-2,0)...C(0,0) C(k,0)
C(k,1) c(k-1,1) C(k-2,1)... 0 C(k,1)
[ fib(n-1)k,fib(n-1)k-1fib(2)1 .....fib(n-2)k,sum[n-1] ] * .......
C(k,k) 0 0 ... 0 C(k,K)
0 0 0 ... 0 1
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> #include<string.h> #define MOD 1000000007 #define maxn 25 long long C[25][25]; long long ret[maxn][maxn]; long long init[maxn][maxn]; long long buf[maxn][maxn]; void matrixMul(long long a[][maxn] , long long b[][maxn] , long long n,long long mod) { long long i,j,k; for(i=0;i<n;i++) { for(j=0;j<n;j++) { buf[i][j]=0; } } for(i=0;i<n;i++) { for(k=0;k<n;k++) { if(a[i][k]==0) continue; for(j=0;j<n;j++) { if(b[k][j]==0) continue; buf[i][j]+=a[i][k]*b[k][j]; if (buf[i][j]>=mod||buf[i][j]<=-mod) { buf[i][j]%=mod; } } } } for(i=0;i<n;i++) { for(j=0;j<n;j++) { a[i][j]=buf[i][j]; } } } void matrixMul(long long n,long long m,long long mod) { long long i,j; for(i=0;i<n;i++) { for(j=0;j<n;j++) { ret[i][j]=(i==j); } } for(;m;m>>=1) { if(m&1) { matrixMul(ret,init,n,mod); } matrixMul(init,init,n,mod); } } void initc() { C[0][0]=C[1][0]=C[1][1]=1; for(int i=2;i<=20;i++) { for(int j=0;j<=i&&j<=20;j++) { if(j==0) C[i][j]=1; else C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD; } } } int main() { initc(); int t,n,k,i,j; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&k); if(n==1) { printf("1\n"); continue; } else if(n==2) { printf("2\n"); continue; } memset(init,0,sizeof(init)); for(i=0;i<=k;i++) { for(j=0;j<=k-i;j++) { init[j][i]=C[k-i][j]; } } for(i=0;i<=k;i++) { init[i][k+1]=C[k][i]; } init[k+1][k+1]=1; matrixMul(k+2,n-2,MOD); long long ans=0; for(i=0;i<=k;i++) { ans=(ans+ret[i][k+1])%MOD; } ans=(ans+2*ret[k+1][k+1])%MOD; printf("%lld\n",ans); } return 0; }
哎,以此题为记,不能再被表面现象吓到了><
下面为升级版,可以用做练习:
hdu 3509.Buge's Fibonacci Number Problem
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> #include<string.h> int MOD; #define maxn 55 long long C[55][55],A[55],B[55],F1[55],F2[55]; long long ret[maxn][maxn]; long long init[maxn][maxn]; long long buf[maxn][maxn]; void matrixMul(long long a[][maxn] , long long b[][maxn] , long long n,long long mod) { long long i,j,k; for(i=0;i<n;i++) { for(j=0;j<n;j++) { buf[i][j]=0; } } for(i=0;i<n;i++) { for(k=0;k<n;k++) { if(a[i][k]==0) continue; for(j=0;j<n;j++) { if(b[k][j]==0) continue; buf[i][j]+=a[i][k]*b[k][j]; if (buf[i][j]>=mod||buf[i][j]<=-mod) { buf[i][j]%=mod; } } } } for(i=0;i<n;i++) { for(j=0;j<n;j++) { a[i][j]=buf[i][j]; } } } void matrixMul(long long n,long long m,long long mod) { long long i,j; for(i=0;i<n;i++) { for(j=0;j<n;j++) { ret[i][j]=(i==j); } } for(;m;m>>=1) { if(m&1) { matrixMul(ret,init,n,mod); } matrixMul(init,init,n,mod); } } void initc(int k) { C[0][0]=C[1][0]=C[1][1]=1; for(int i=2;i<=k;i++) { for(int j=0;j<=i&&j<=k;j++) { if(j==0) C[i][j]=1; else C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD; } } } int main() { long long t,n,k,i,j,f1,f2,a,b; scanf("%I64d",&t); while(t--) { scanf("%I64d%I64d%I64d%I64d%I64d%I64d%I64d",&f1,&f2,&a,&b,&k,&n,&MOD); initc(k); long long ans=0; F1[0]=F2[0]=1; for(i=1;i<=k;i++) { F1[i]=(F1[i-1]*f1)%MOD; F2[i]=(F2[i-1]*f2)%MOD; } if(n==1) { ans=F1[k]; printf("%I64d\n",ans); continue; } else if(n==2) { ans=F1[k]; ans=(ans+F2[k])%MOD; printf("%I64d\n",ans); continue; } memset(init,0,sizeof(init)); A[0]=B[0]=1; for(i=1;i<=k;i++) { A[i]=(A[i-1]*a)%MOD; B[i]=(B[i-1]*b)%MOD; } for(i=0;i<=k;i++) { for(j=0;j<=k-i;j++) { if(j>k-i) init[j][i]=0; else init[j][i]=((C[k-i][j]*A[k-i-j])%MOD*B[j])%MOD; } } for(i=0;i<=k;i++) { init[i][k+1]=((C[k][i]*A[k-i])%MOD*B[i])%MOD; } init[k+1][k+1]=1; matrixMul(k+2,n-2,MOD); for(i=0;i<=k;i++) { ans=(ans+((F2[k-i]*F1[i])%MOD)*ret[i][k+1])%MOD; } long long temp; temp=F1[k]; temp=(temp+F2[k])%MOD; ans=(ans+(temp*ret[k+1][k+1])%MOD)%MOD; printf("%I64d\n",ans); } return 0; }