题解 P3990 [SHOI2013]超级跳马

Link

显然有 DP 做法,f(i,j) 表示走到第 i 行第 j 列的方案数量。

有转移方程f(i,j)=f(i1,j1)+f(i,j1)+f(i+1,j1)+i=1j2f(i1,j12i)+f(i,j12i)+f(i+1,j12i)

这个转移方程转移复杂度太高,发现后面那个式子即为 f(i,j2)

所以有更简洁的转移方程f(i,j)=f(i1,j1)+f(i,j1)+f(i+1,j1)+f(i,j2)

然后发现,数据范围 n50,m109,暴力转移 O(nm),过高。

考虑用矩阵优化。

矩阵中有上两列每行的状态。如 n=3 时有转移矩阵

[110100111010011001100000010000001000]×[f(1,i1)f(2,i1)f(3,i1)f(1,i2)f(2,i2)f(3,i2)]=[f(1,i)f(2,i)f(3,i)f(1,i1)f(2,i1)f(3,i1)]

这个矩阵的构造,以 f(2,i) 为例f(2,i)=1×f(1,i1)+1×f(2,i1)+1×f(3,i1)+0×f(1,i2)+1×f(2,i2)+0×f(3,i2)

其对应的系数即为初始矩阵的第 2 行。

矩阵快速幂即可。

因为最初第一列不需要转移,所以将 mm1,并特判一下 m=2 的情况,然后会发现,在 计算 f(1,3) 时,会有从 f(1,1) 来的转移,然而 f(1,1) 并没有在其之前列的转移,导致多算了一次。所以到 f(n,m) 时,多出的方案数,即为从 (1,1)(n,m2) 的方案数,即多出 f(n,m2),减去它即可。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e2 + 10, P = 30011;
int n, m;
struct Matrix {
    int a[N][N];
    Matrix() { memset(a, 0, sizeof(a)); }
    void init() {
        for(int i = 1; i <= (n << 1); i++) a[i][i] = 1;
    }
    friend Matrix operator * (Matrix a, Matrix b) {
        Matrix res;
        for(int i = 1; i <= (n << 1); i++)
            for(int j = 1; j <= (n << 1); j++)
                for(int k = 1; k <= (n << 1); k++)
                    res.a[i][j] = (res.a[i][j] + a.a[i][k] * b.a[k][j]) % P;
        return res;      
    }
} base;
Matrix qpow(Matrix a, int k) {
    Matrix res; res.init();
    for(; k; a = a * a, k >>= 1)
        if(k & 1) res = res * a;
    return res;
}
void build() {
    for(int i = 1; i <= n; i++)
        for(int j = max(i - 1, 1); j <= min(i + 1, n); j++)
            base.a[i][j] = 1;
    for(int i = 1; i <= n; i++)
        base.a[i][i + n] = base.a[i + n][i] = 1;
}
int main() {
    scanf("%d%d", &n, &m);
    if(m == 2) {
        if(n <= 2) printf("1");
        else printf("0");
        return 0;
    }
    build();
    m -= 2;//因为最后有一次单独算,所以m多减1
    Matrix ans = qpow(base, m);
    int s = ans.a[1][n << 1];
    ans = ans * base;
    int t = ans.a[1][n];
    printf("%d", (t - s + P) % P);
    return 0;
}
posted @   Terac  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示