题目链接

题目

题目描述

在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\) 列,分类讨论:

  1. 不放任何炮。转移方程:

    \[dp[i][j][k] = dp[i][j][k] + dp[i - 1][j][k]
    \]
  2. 放一个,可以选一个放了一个的列共 \(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.
    \]
  3. 放两个,可以选两个没有放的列有 \(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 中国象棋的更多相关文章

  1. BZOJ 1801: [Ahoi2009]chess 中国象棋( dp )

    dp(i, j, k)表示考虑了前i行, 放了0个炮的有j列, 放了1个炮的有k列. 时间复杂度O(NM^2) -------------------------------------------- ...

  2. BZOJ_1801_[Ahoi2009]chess 中国象棋_DP

    BZOJ_1801_[Ahoi2009]chess 中国象棋_DP Description 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放置方法,中国像 ...

  3. 【BZOJ1801】[Ahoi2009]chess 中国象棋 DP

    [BZOJ1801][Ahoi2009]chess 中国象棋 Description 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放置方法,中国像棋中炮 ...

  4. BZOJ1801 Ahoi2009 chess 中国象棋 【DP+组合计数】*

    BZOJ1801 Ahoi2009 chess 中国象棋 Description 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放置方法,中国像棋中炮的行 ...

  5. Bzoj 1081 [Ahoi2009] chess 中国象棋

    bzoj 1081 [Ahoi2009] chess 中国象棋 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1801 状态比较难设,的确 ...

  6. BZOJ1801 [Ahoi2009]chess 中国象棋(DP, 计数)

    题目链接 [Ahoi2009]chess 中国象棋 设$f[i][j][k]$为前i行,$j$列放了1个棋子,$k$列放了2个棋子的方案数 分6种情况讨论,依次状态转移. #include <b ...

  7. bzoj1801: [Ahoi2009]chess 中国象棋(DP)

    1801: [Ahoi2009]chess 中国象棋 题目:传送门 题解: 表示自己的DP菜的抠脚 %题解... 定义f[i][j][k]表示前i行 仅有一个棋子的有j列 有两个棋子的有k个 的方案数 ...

  8. [luogu2051][bzoj1801][AHOI2009]chess中国象棋【动态规划】

    题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法.大家肯定很清楚,在中国象棋中炮的行走方式是 ...

  9. bzoj 1801: [Ahoi2009]chess 中国象棋

    Description 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放置方法,中国像棋中炮的行走方式大家应该很清楚吧. Input 一行包含两个整数N, ...

  10. BZOJ1801:[Ahoi2009]chess 中国象棋

    Time Limit: 10 Sec  Memory Limit: 64 MB Description 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放置 ...

随机推荐

  1. 基于AHB_BUS Clac slave详解

    基于AHB-APB BUS slave详解 1.目录 高内聚:让模块的功能更集中,更单一. AMBA总线例子,需要有一个模块和AMBA进行交互,就可以单独将与AHB总线进行交互的部分作为一个模块.经常 ...

  2. 【Kafka系列】(一)Kafka入门

    有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址 系列文章地址 Kafka是什么? 一句话概括:Apache K ...

  3. [转帖]TLS 加速技术:Intel QuickAssist Technology(QAT)解决方案

    https://zhuanlan.zhihu.com/p/631184323   3 人赞同了该文章 作者:vivo 互联网服务器团队- Ye Feng 本文介绍了 Intel QAT 技术方案,通过 ...

  4. JDBC针对SQLServer的sendStringParametersAsUnicode=false的验证

    JDBC针对SQLServer的sendStringParametersAsUnicode=false的验证 背景 部分客户的SQLServer数据库出现了大量死锁的情况. 虽然部分客户并没有反馈死锁 ...

  5. [转帖]Python执行Linux系统命令的4种方法

    https://www.cnblogs.com/pennyy/p/4248934.html (1) os.system 仅仅在一个子终端运行系统命令,而不能获取命令执行后的返回信息 代码如下: sys ...

  6. SQLServer性能优化之二

    SQLServer性能优化之二 背景 优化了机器的硬件配置之后性能好了很多 但是偶尔还是会出现阻塞. SQL总是奇奇怪怪的. 其实第一天时就感觉可能是索引存在问题. 但是dbcc 重建所有数据库的索引 ...

  7. 阿里云IPV6 创建虚拟机的过程

    阿里云IPV6 创建虚拟机的过程 背景 IPV6 已经越来越广泛的应用. 想在外网开通一下IPV6,发现还有一些坑. 这里总结一下. 备忘. 开通方式 1. 登录阿里云的控制台, 打开云服务器ECS的 ...

  8. [转帖]005、体系结构之TiKV_Raft日志

    Raft日志 1.Raft与Multi Raft 2.Raft 日志复制 2.1.复制流程总览 2.2.Propose 2.3.Append 2.3.Replicate(Append) 2.4 Com ...

  9. Windows平台文件拆分与完整性检查的过程

    Windows平台文件拆分与完整性检查的过程 场景 有时候在没有linux主机的情况下, 自己下载下来的文件比较大. 比较难以上传到一些特殊的系统/主机上面. 这个时候需要将文件进行拆分. 所以可以通 ...

  10. [转帖]MinIO Client(mc)完全指南

    https://www.cnblogs.com/lvzhenjiang/p/14944821.html 目录 一.获取MinIO Client(mc) 1.1 docker版 1.2 Homebrew ...