首页 > 代码库 > 矩阵十题【七】vijos 1067 Warcraft III 守望者的烦恼

矩阵十题【七】vijos 1067 Warcraft III 守望者的烦恼

题目链接:https://vijos.org/p/1067

题目大意:给你一个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;
}