VOJ 1067 Warcraft III 守望者的烦恼 (矩阵高速功率+dp)

主题链接

明显的

dp[n] = dp[n-k] + dp[n-k+1] + ... +dp[n-1];

然后要用矩阵来优化后面的状态转移。

也就是矩阵

0 1 0 0    a     b

0 0 1 0 * b =  c

0 0 0 1    c     d

1 1 1 1    d    a+b+c+d

然后跑高速幂

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define N 10

using namespace std;
const int mod = 7777777;
typedef long long LL;

struct matrix
{
    LL a[10][10];
}origin;

int n,m;

matrix multiply(matrix x,matrix y)
{
    matrix temp;
    memset(temp.a,0,sizeof(temp.a));
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            for(int k=0;k<n;k++)
            {
                temp.a[i][j]+=x.a[i][k]*y.a[k][j];
                temp.a[i][j]=(temp.a[i][j])%mod;
            }
        }
    }
    return temp;
}

matrix matmod(matrix A,int k)
{
    matrix res;

    memset(res.a,0,sizeof res.a);
    for(int i=0;i<n;i++)res.a[i][i]=1;

    while(k)
    {
        if(k&1)
        res=multiply(res,A);
        k>>=1;
        A=multiply(A,A);
    }
    return res;
}

void print(matrix x)
{
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        cout<<" "<<x.a[i][j];
        puts("");
    }
    printf("---------------\n");
}

int main()
{
    int k;
    while(cin>>n>>k)
    {
        memset(origin.a,0,sizeof origin.a);

        origin.a[0][0]=1;

        for(int i=1;i<=n;i++)
        {
            origin.a[i][0]=1;
            for(int j=0;j<i;j++)
            {
                origin.a[i][0]+=origin.a[j][0];
            }
        }
       // print(origin);
        matrix res;
        memset(res.a,0,sizeof res.a);

        for(int i=0;i<n-1;i++)
        {
            res.a[i][i+1]=1;
        }
        for(int i=0;i<n;i++)res.a[n-1][i]=1;
        //print(res);
        res=matmod(res,k-1);

        LL fans=0;
        for(int i=0;i<n;i++)
        {
            fans+=res.a[0][i]*origin.a[i][0];
            fans%=mod;
        }
        cout<<fans<<endl;
    }
    return 0;
}

版权声明:本文博客原创文章。博客,未经同意,不得转载。

时间: 2024-08-02 00:28:26

VOJ 1067 Warcraft III 守望者的烦恼 (矩阵高速功率+dp)的相关文章

VOJ 1067 Warcraft III 守望者的烦恼 (矩阵快速幂+dp)

题目链接 显然可知 dp[n] = dp[n-k] + dp[n-k+1] + ... +dp[n-1]; 然后要用矩阵来优化后面的状态转移. 也就是矩阵 0 1 0 0    a     b 0 0 1 0 * b =  c 0 0 0 1    c     d 1 1 1 1    d    a+b+c+d 然后跑快速幂 #include <iostream> #include <cstdio> #include <algorithm> #include <c

矩阵十题【七】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

矩阵经典题目七:Warcraft III 守望者的烦恼(矩阵加速递推)

https://www.vijos.org/p/1067 很容易推出递推式f[n] = f[n-1]+f[n-2]+......+f[n-k]. 构造矩阵的方法:构造一个k*k的矩阵,其中右上角的(k-1)*(k-1)的矩阵是单位矩阵,第k行的每个数分别对应f[n-1],f[n-2],,f[n-k]的系数.然后构造一个k*1的矩阵,它的第i行代表f[i],是经过直接递推得到的.设ans[][]是第一个矩阵的n-k次幂乘上第二个矩阵,f[n]就是ans[k][1]. 注意:用__int64 #in

[Vijos1067]Warcraft III 守望者的烦恼(DP + 矩阵优化)

传送门 可知 f[i] = f[i - 1] + f[i - 2] + ... + f[i - k] 直接矩阵优化就好了 #include <cstdio> #include <cstring> #define p 7777777 #define LL long long int n, k; struct Matrix { int n, m; LL a[11][11]; Matrix() { n = m = 0; memset(a, 0, sizeof(a)); } }; inli

[矩阵乘法][DP]Vijos1067 Warcraft III 守望者的烦恼

题目梗概 n个单位的路程,主角每次最多可以走k个单位(也就是每次可以走1-k个单位),问最后到第n个监狱的方法数. 思考 DP转移方程并不难推导: dp[i]表示第i个监狱的方法数 $dp\left [ i \right ] = dp\left [ i-1 \right ] + dp\left [ i-2 \right ]\cdots \cdots + dp\left [ i-k-1 \right ]$ 但是这个n有点太大了,所以我们需要对DP方程进行优化. 仔细观察转移方程会发现,每次都是加上

Warcraft III 守望者的烦恼

题目链接: 这道题跟斐波那契数列类似,快速幂矩阵随便推一推就出来了! #pragma GCC optimize("O3") #include <bits/stdc++.h> using namespace std; #define ll long long #define re register #define pb push_back #define fi first #define se second const int N=1e6+10; const int mod=

HDU 2842 Chinese Rings(矩阵高速功率+递归)

职务地址:HDU 2842 这个游戏是一个九连环的游戏. 如果当前要卸下前n个环.由于要满足前n-2个都卸下,所以要先把前n-2个卸下.须要f(n-2)次.然后把第n个卸下须要1次,然后这时候要卸下第n-1个.然后此时前n-2个都已经被卸下了.这时候把前n-2个都卸下与都装上所需的次数是一样的.由于卸下与装上的规则是一样的. 所以又须要f(n-2)次.这时候前n-1个都在上面,卸下前n-1个须要f(n-1)次. 所以.总共须要2*f(n-2)+f(n-1)+1次. 然后构造例如以下矩阵. 1,2

POJ 3070 Fibonacci(矩阵高速功率)

职务地址:POJ 3070 用这个题学会了用矩阵高速幂来高速求斐波那契数. 依据上个公式可知,第1行第2列和第2行第1列的数都是第n个斐波那契数.所以构造矩阵.求高速幂就可以. 代码例如以下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include

vijosP1067Warcraft III 守望者的烦恼

链接:https://vijos.org/p/1067 [思路] 矩阵乘法. 可以得出递推式:      f[i]=sum{ f[n-1],f[n-2]…f[n-k] }   矩阵乘法加速转移如下: 1.   原始矩阵F  1 x k: |  1,0,0,0,0,…| 2.   转移矩阵T  k x k: | 1 , 0,  …  | | 1, 1 ,  …  | | 1, 0, 1,0  | | 1 0, 0, 1  | 即有如下转移: (上图转移矩阵有错) [代码] 1 #include<c