NC19885 [AHOI2009]CHESS 中国象棋
题目
题目描述
在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮。 请问有多少种放置方法,中国像棋中炮的行走方式大家应该很清楚吧.一个炮要能攻击另一个炮他们必须要处于同一行或者一列且他们之间有且仅有一个棋子.
输入描述
一行包含两个整数N,M,中间用空格分开.
输出描述
输出所有的方案数,由于值比较大,输出其mod 9999973
示例1
输入
1 3
输出
7
备注
除了 \(3\) 个格子里都塞满了炮以外,其它方案都是可行的,所以一共有 \(2 \times 2 \times 2-1=7\) 种方案。
数据规模与约定
对于 \(30\%\) 的数据,\(n\) 和 \(m\) 均不超过 \(6\) 。
对于 \(50\%\) 的数据,\(n\) 和 \(m\) 至少有一个数不超过 \(8\) 。
对于 \(100\%\) 的数据,\(1 \leq n,m \leq 100\) 。
题解
知识点:计数dp,排列组合。
这道题是一个分类计数dp,考虑摆第 \(i\) 行时,需要且只要知道之前摆一个炮和摆两个炮的列数,不可能有摆超过两个炮的列,一行也不会有超过两个炮。刷表法免去边界问题,设 \(dp[i][j][k]\) 为摆第 \(i\) 行,放一个炮的有 \(j\) 列,放两个炮的有 \(k\) 列,分类讨论:
不放任何炮。转移方程:
\[dp[i][j][k] = dp[i][j][k] + dp[i - 1][j][k]
\]放一个,可以选一个放了一个的列共 \(j\),也可以放在没有放的列 \(m-j-k\) 。转移方程:
\[\left \{
\begin{array}{l}
dp[i][j + 1][k] = dp[i][j + 1][k] + dp[i - 1][j][k] \cdot (m - j - k) &,m - j - k \geq 1\\
dp[i][j - 1][k + 1] = dp[i][j - 1][k + 1] + dp[i - 1][j][k] \cdot j &,j \geq 1
\end{array}
\right.
\]放两个,可以选两个没有放的列有 \(C_{m-j-k}^2\) ,可以选两个放一个的列有 \(C_{j}^2\) ,可以一个选没有放的列一个选放一个的列有 \((m-j-k) \cdot j\) 。注意不能认为先放一个没有的列然后把这个算进放一个的列,这个包括了把两个同时放在一个没有选的列里面,会被一下行枚举到,所以不需要包括。转移方程:
\[\left \{
\begin{array}{l}
dp[i][j + 2][k] = dp[i][j + 2][k] + C_{m-j-k}^2 \cdot dp[i - 1][j][k]) &,m - j - k \geq 2\\
dp[i][j][k + 1] = dp[i][j][k + 1] + dp[i - 1][j][k] \cdot (m - j - k) \cdot j &,j \geq 1\\
dp[i][j - 2][k + 2] = dp[i][j - 2][k + 2] + C_{j}^2 \cdot dp[i - 1][j][k] &,j \geq 2
\end{array}
\right.
\]
时间复杂度 \(O(nm^2)\)
空间复杂度 \(O(nm^2)\)
代码
#include <bits/stdc++.h>
using namespace std;
const int mod = 9999973;
int dp[107][107][107];
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m;
cin >> n >> m;
dp[0][0][0] = 1;
for (int i = 1;i <= n;i++) {
for (int j = 0;j <= m;j++) {
for (int k = 0;j + k <= m;k++) {
///一个也不放
dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j][k]) % mod;
///放一个
if (m - j - k >= 1) dp[i][j + 1][k] = (dp[i][j + 1][k] + 1LL * dp[i - 1][j][k] * (m - j - k)) % mod;
if (j >= 1) dp[i][j - 1][k + 1] = (dp[i][j - 1][k + 1] + 1LL * dp[i - 1][j][k] * j) % mod;
///放两个
if (m - j - k >= 2) dp[i][j + 2][k] = (dp[i][j + 2][k] + 1LL * (m - j - k) * (m - j - k - 1) / 2 % mod * dp[i - 1][j][k]) % mod;
if (m - j - k >= 1 && j >= 1) dp[i][j][k + 1] = (dp[i][j][k + 1] + 1LL * (m - j - k) * j % mod * dp[i - 1][j][k]) % mod;///不能先摆一个得到j+1列一个子再摆另一个,因为被包括在全放在没有子的情况里了
if (j >= 2) dp[i][j - 2][k + 2] = (dp[i][j - 2][k + 2] + 1LL * j * (j - 1) / 2 % mod * dp[i - 1][j][k]) % mod;
}
}
}
int ans = 0;
for (int i = 0;i <= m;i++) {
for (int j = 0;i + j <= m;j++) {
ans = (ans + dp[n][i][j]) % mod;
}
}
cout << ans << '\n';
return 0;
}
NC19885 [AHOI2009]CHESS 中国象棋的更多相关文章
- BZOJ 1801: [Ahoi2009]chess 中国象棋( dp )
dp(i, j, k)表示考虑了前i行, 放了0个炮的有j列, 放了1个炮的有k列. 时间复杂度O(NM^2) -------------------------------------------- ...
- BZOJ_1801_[Ahoi2009]chess 中国象棋_DP
BZOJ_1801_[Ahoi2009]chess 中国象棋_DP Description 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放置方法,中国像 ...
- 【BZOJ1801】[Ahoi2009]chess 中国象棋 DP
[BZOJ1801][Ahoi2009]chess 中国象棋 Description 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放置方法,中国像棋中炮 ...
- BZOJ1801 Ahoi2009 chess 中国象棋 【DP+组合计数】*
BZOJ1801 Ahoi2009 chess 中国象棋 Description 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放置方法,中国像棋中炮的行 ...
- Bzoj 1081 [Ahoi2009] chess 中国象棋
bzoj 1081 [Ahoi2009] chess 中国象棋 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1801 状态比较难设,的确 ...
- BZOJ1801 [Ahoi2009]chess 中国象棋(DP, 计数)
题目链接 [Ahoi2009]chess 中国象棋 设$f[i][j][k]$为前i行,$j$列放了1个棋子,$k$列放了2个棋子的方案数 分6种情况讨论,依次状态转移. #include <b ...
- bzoj1801: [Ahoi2009]chess 中国象棋(DP)
1801: [Ahoi2009]chess 中国象棋 题目:传送门 题解: 表示自己的DP菜的抠脚 %题解... 定义f[i][j][k]表示前i行 仅有一个棋子的有j列 有两个棋子的有k个 的方案数 ...
- [luogu2051][bzoj1801][AHOI2009]chess中国象棋【动态规划】
题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法.大家肯定很清楚,在中国象棋中炮的行走方式是 ...
- bzoj 1801: [Ahoi2009]chess 中国象棋
Description 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放置方法,中国像棋中炮的行走方式大家应该很清楚吧. Input 一行包含两个整数N, ...
- BZOJ1801:[Ahoi2009]chess 中国象棋
Time Limit: 10 Sec Memory Limit: 64 MB Description 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放置 ...
随机推荐
- spring boot 集成配置阿里 Druid监控配置
本文为博主原创,转载请注明出处: github 地址如下:https://github.com/alibaba/druid/wiki 其相关问题也可参考:https://github.com/alib ...
- Python追踪内存占用
技术背景 当我们需要对python代码所占用的内存进行管理时,首先就需要有一个工具可以对当前的内存占用情况进行一个追踪.虽然在Top界面或者一些异步的工具中也能够看到实时的内存变化,还有一些工具可以统 ...
- pycharm设置保存时自动格式化代码(Auto Reformat Code)
原文:https://blog.csdn.net/qq_41906934/article/details/124631826 1.手动格式化代码 Code -> Reformat Code 格式 ...
- [转帖]harbor镜像仓库清理操作
https://www.cnblogs.com/FengGeBlog/p/15517706.html 两年前清理过一次harbor镜像,而现在又要面临清镜像的操作了,笔者目前所在的公司镜像是存放在ce ...
- [转帖]tidb 搭建私有镜像库
https://docs.pingcap.com/zh/tidb/stable/tiup-mirror 在构建私有云时,通常会使用隔离的网络环境,此时无法访问 TiUP 的官方镜像.因此,TiUP 提 ...
- [转帖]Kingbase实现Oracle userenv函数功能
目录 1. 问题 2. 文档概述 3. Oracle userenv()函数功能调研 3.1. 函数名称/函数原型 3.2. 函数功能 3.3. 参数介绍 3.3.1. Parameter 3.4. ...
- [转帖]VCSA证书过期问题处理
1. 故障现象 2022年10月25日,登陆VC报错. 按照报错信息,结合官方文档,判断为STS证书过期导致. vCenter Server Appliance (VCSA) 6.5.x, 6.7. ...
- [转帖]SPECjvm测试工具详解
ARM服务器测试大纲中指定了要使用specjvm测试Java虚拟机性能,所以就上网找开源的测试套. 简介 SPECjvm2008(java虚拟机基准测试)是用来测试java运行环境(JRE)性能的基准 ...
- 公司内部Oracle RAC测试环境的简单使用说明.
1. 公司内部要测试Oracle RAC系统的创建与测试工作. 因为Oracle RAC 主要需要 多个网段以及共享存储, 直接使用ESXi搭建比较复杂 所以我这边使用vagrant的方式搭建Orac ...
- k8s单master集群通过备份etcd还原集群
准备环境 通过kubeadm 安装的单master kubernetes 1.19+ 集群 容器环境:containerd 客户端工具:kubeadm.kubectl.etcdctl.crictl 备 ...