题解 P3990 [SHOI2013]超级跳马
显然有 DP 做法,
有转移方程
这个转移方程转移复杂度太高,发现后面那个式子即为
所以有更简洁的转移方程
然后发现,数据范围
考虑用矩阵优化。
矩阵中有上两列每行的状态。如
这个矩阵的构造,以
其对应的系数即为初始矩阵的第
矩阵快速幂即可。
因为最初第一列不需要转移,所以将
#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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异