题目大意:给你一个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 守望者的烦恼,布布扣,bubuko.com
矩阵十题【七】vijos 1067 Warcraft III 守望者的烦恼
原文:http://blog.csdn.net/u010468553/article/details/38460575