[Shoi2013]超级跳马(DP+矩阵乘法)

本文介绍了一种使用矩阵快速幂优化动态规划(DP)算法的方法,通过将状态分为奇偶两类,将O(m^2n)的时间复杂度优化至O(nm)。文章详细解释了如何构建矩阵并进行快速幂运算,最终求得特定位置的方案数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

设f[i][j]表示方案数,显然有一个O(m2n)的暴力DP法,但实际上可以按距离当前位置的奇偶性分成s1[i][j]和s2[i][j],然后这个暴力DP可以优化到O(nm)的暴力。于是有这样的递推式:s1[i+1][j]=s2[i][j]+s1[i][j−1]+s1[i][j]+s1[i][j+1],s2[i+1][j]=s1[i][j],这个显然能够矩乘的,然后就直接转移即可,答案就是s1[m][n]−s2[m−1][n]。

#include<bits/stdc++.h>
using namespace std;
const int mod=30011;
int n,m;
struct mat{
    int a[105][105];
    mat(){memset(a,0,sizeof a);}
}A,B,S;
mat operator*(mat a,mat b)
{
    mat c;
    for(int i=1;i<=2*n;i++)
    for(int j=1;j<=2*n;j++)
    for(int k=1;k<=2*n;k++)
    c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
    return c;
}
mat qpow(mat a,int b)
{
    mat ret;for(int i=1;i<=2*n;i++)ret.a[i][i]=1;
    while(b)
    {
        if(b&1)ret=ret*a;
        a=a*a,b>>=1;
    }
    return ret;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)S.a[i][i]=S.a[i+n][i]=S.a[i][i+n]=1;
    for(int i=1;i<n;i++)S.a[i+1][i]=S.a[i][i+1]=1;
    A=qpow(S,m-2),B=A*S;
    printf("%d",(B.a[1][n]-A.a[1][n<<1]+mod)%mod);
}
View Code

 

转载于:https://www.cnblogs.com/hfctf0210/p/11014228.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值