题目大意:给你一个k以及n,k代表最多走的步数,n代表一共要走的步数。
问一共有多少种方法,结果mod7777777
题目意思是很明了,具体的公式也能推出来
状态转移方程为:f[n]=f[n-1]+f[n-2]+....f[n-k]。
f[0]=1
当k=1, f[1]=1;
f[2]=f[1]=1;
f[3]=f[2]=1;
f[4]=f[3]=1;
当k=2, f[1]=1;
f[2]=f[1]+f[0]=2;
f[3]=f[2]+f[1]=3;
f[4]=f[3]+f[2]=5;
当k=3, f[1]=1;
f[2]=f[1]+f[0]=2;
f[3]=f[2]+f[1]+f[0]=4;
f[4]=f[3]+f[2]+f[1]=7;
k的数据量只有10,所以我们构造出一个10*10的矩阵,本题主要考察的是矩阵快速幂以及构造这个矩阵。
若k等于4
【 [ 0 1 0 0] [f(k-4)] [f(k-3)]
[ 0 0 1 0] * [f(k-3)] = [f(k-2)]
[ 0 0 0 1] [f(k-2)] [f(k-1)]
[ 1 1 1 1] 】 [f(k-1)] [f( k )]
根据上面的例子我们可以很容易构造出这个矩阵出来。
#include<stdio.h> #include<string.h> #define N 11 #define M 7777777 struct Matrix { __int64 a[N][N]; }res,tmp,origin,A,ans; int n,m,f[N]; Matrix mul(Matrix x,Matrix y) { int i,j,k; memset(tmp.a,0,sizeof(tmp.a)); for(i=1;i<=n;i++) for(j=1;j<=n;j++) for(k=1;k<=n;k++) { tmp.a[i][j]+=(x.a[i][k]*y.a[k][j])%M; tmp.a[i][j]%=M; } return tmp; } void quickpow(int k) //矩阵快速幂 { int i; memset(res.a,0,sizeof(res.a)); for(i=1;i<=n;i++) res.a[i][i]=1; while(k) { if(k&1) res=mul(res,A); A=mul(A,A); k>>=1; } } int main() { int k,i,j; while(scanf("%d%d",&k,&m)!=EOF) { memset(f,0,sizeof(f)); f[0]=1; for(i=1;i<=k;i++) //构造前k项 for(j=0;j<i;j++) f[i]+=f[j]; memset(A.a,0,sizeof(A.a)); for(i=2;i<=k;i++) //构造矩阵A A.a[i][i-1]=1; for(i=1;i<=k;i++) A.a[i][k]=1; n=k; quickpow(m-k); //A^(n-k) memset(origin.a,0,sizeof(origin.a)); for(i=1;i<=k;i++) //前k项的矩阵[f(1),f(2),f(3)....f(k)] origin.a[1][i]=f[i]; ans=mul(origin,res); //[f(1),f(2),f(3)....f(k)] * A^(n-k) printf("%d\n",ans.a[1][n]%M); } return 0; }
矩阵十题【七】vijos 1067 Warcraft III 守望者的烦恼
时间: 2024-11-08 05:39:04