[AHOI2009] 中国象棋
[AHOI2009] 中国象棋
蛮简单的一道 .
显然, 每行每列都最多只有 个炮, 所以我们设 表示第 行, 列有 个炮, 列有 个炮的方案数.
然后转移就很简单了, 只需要枚举当前行放的一个或者两个炮放到哪里就行了.
像这种合法不合法只与单行或单列的数量有关的, 我们设状态就可以只存数量为多少的行或列的数量就可以了, 转移的时候用组合来计算我们共有多少种转移方案.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int read() {
int x = 0, f = 1;
char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
return x * f;
}
const int N = 105, mod = 9999973;
int n, m;
ll ans, f[N][N][N];
int main() {
n = read(), m = read();
f[0][0][0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = m; j >= 0; j--) {
for (int k = m - j; k >= 0; k--) {
f[i][j][k] += f[i - 1][j][k];
if (m - j - k) f[i][j + 1][k] = (f[i][j + 1][k] + f[i - 1][j][k] * (m - j - k)) % mod;
if (m - j - k > 1) f[i][j + 2][k] = (f[i][j + 2][k] + (f[i - 1][j][k] * (m - j - k) * (m - j - k - 1) >> 1)) % mod;
if (j) f[i][j - 1][k + 1] = (f[i][j - 1][k + 1] + f[i - 1][j][k] * j) % mod;
if (j > 1) f[i][j - 2][k + 2] = (f[i][j - 2][k + 2] + (f[i - 1][j][k] * j * (j - 1) >> 1)) % mod;
if (m - j - k && j) f[i][j][k + 1] = (f[i][j][k + 1] + f[i - 1][j][k] * j * (m - j - k)) % mod;
}
}
}
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= m - i; j++) {
ans += f[n][i][j];
}
}
printf("%lld", ans % mod);
return 0;
}
看不见我看不见我看不见我
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】博客园的心动:当一群程序员决定开源共建一个真诚相亲平台
【推荐】Flutter适配HarmonyOS 5知识地图,实战解析+高频避坑指南
【推荐】凌霞软件回馈社区,携手博客园推出1Panel与Halo联合终身会员
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一则复杂 SQL 改写后有感
· golang中写个字符串遍历谁不会?且看我如何提升 50 倍
· C# 代码如何影响 CPU 缓存速度?
· 智能桌面机器人:使用 .NET 为树莓派开发 Wifi 配网功能
· C# 模式匹配全解:原理、用法与易错点
· 一则复杂 SQL 改写后有感
· 曾经风光无限的 Oracle DBA 已经落伍了吗?
· 接口被刷百万QPS,怎么防?
· C# 锁机制全景与高效实践:从 Monitor 到 .NET 9 全新 Lock
· 一个开源免费、功能丰富的 WPF 自定义控件资源库