【题目大意】

叫你在\(n×m\)的棋盘上放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,问有多少种放置方法。

【关键词】

  • \(DP\)
  • 分类讨论
  • 乘法和加法原理

【分析】

仔细观察就会发现,棋盘中每行,每列只有放\(0\),\(1\),\(2\)个三种方案。如果我们把状态量设为列,那么知道任意两种方案的列数,即可用总列数减去它得到另一种方案的列数。

我们设状态方程:\(f[i][j][k]\),表示的是前\(i\)行,其中\(j\)列有\(1\)个棋子,\(k\)列有\(2\)个棋子的总方案数。

那么对于行的转移,我们有三种情况。

  1. 在第\(i\)行不放棋子。
  2. 在第\(i\)行放\(1\)个棋子。
  3. 在第\(i\)行放\(2\)个棋子。
  • 不放棋子,即\(f[i][j][k]=f[i-1][j][k]\)。

  • 放\(1\)个棋子,又分两种情况:

    • 放在有\(1\)个棋子的列上,\(j+1\)列都可以放。即\(f[i][j][k]+=f[i-1][j+1][k-1]*(j+1)\)。
    • 放在没有棋子的列上,\(m-(j-1)-k\)列都可放。即\(f[i][j][k]+=f[i-1][j-1][k]*(m-j-k+1)\)
  • 放\(2\)个棋子,分三种情况:

    • \(2\)个都放在没有棋子的列上。即\(f[i][j][k]+=f[i-1][j-2][k]*C_{m-(j-2)-k}^{2}\)。
    • \(2\)个都放在有\(1\)个棋子的列上。即\(f[i][j][k]+=f[i-1][j+2][k-2]*C_{j+2}^2\)。
    • \(1\)个放在没有棋子的列上,另一个放在有\(1\)个棋子的列上。即\(f[i][j][k]+=f[i-1][j][k-1]*(m-j-k+1)\)。

然后就可以\(A\)掉了,哦,记得开\(long long\)。。。

【Code】

#pragma GCC optimize("O3")
#pragma GCC optimize("O2")
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define ll long long
#define R register
using namespace std;
const int MAX = 100 + 5;
const int mod = 9999973;
inline int read(){
int f = 1, x = 0;char ch;
do { ch = getchar(); if (ch == '-') f = -1; } while (ch < '0'||ch>'9');
do {x = x*10+ch-'0'; ch = getchar(); } while (ch >= '0' && ch <= '9');
return f*x;
}
inline ll c(ll x) {
return (x * (x - 1) / 2) % mod;
}
int n, m;
ll f[MAX][MAX][MAX], ans;
int main(){
n = read(), m = read();
f[0][0][0] = 1;
for (R int i = 1;i <= n; ++i) {
for (R int j = 0;j <= m; ++j) {
for (R int k = 0;k <= m - j; ++k) {
f[i][j][k] = f[i-1][j][k];
if (k > 0) {
f[i][j][k] += (f[i-1][j+1][k-1] * (j+1)) % mod;
f[i][j][k] %= mod; f[i][j][k] += (f[i-1][j][k-1] * j * (m-j-k+1)) %mod;
f[i][j][k] %= mod;
}
if (j > 0) {
f[i][j][k] += (f[i-1][j-1][k] * (m-j-k+1)) %mod;
f[i][j][k] %= mod;
}
if (k > 1) {
f[i][j][k] += (f[i-1][j+2][k-2] * c(j+2)) % mod;
f[i][j][k] %= mod;
}
if (j > 1) {
f[i][j][k] += (f[i-1][j-2][k] * c(m-j-k+2)) % mod;
f[i][j][k] %= mod;
}
}
}
}
for (R int i = 0;i <= m; ++i) {
for (R int j = 0;j <= m; ++j) {
ans += f[n][i][j];
ans %= mod;
}
}
printf("%lld", (ans + mod) % mod);
return 0;
}

【简●解】[AHOI2009]中国象棋的更多相关文章

  1. [Luogu P2051] [AHOI2009]中国象棋 (状压DP->网格DP)

    题面 传送门:https://www.luogu.org/problemnew/show/P2051 Solution 看到这题,我们不妨先看一下数据范围 30pt:n,m<=6 显然搜索,直接 ...

  2. 洛谷 P2051 [AHOI2009]中国象棋 解题报告

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

  3. luogu 2051 [AHOI2009]中国象棋

    luogu 2051 [AHOI2009]中国象棋 真是一道令人愉♂悦丧心并框的好题... 首先"没有一个炮可以攻击到另一个炮"有个充分条件就是没有三个炮在同一行或同一列.证明:显 ...

  4. [洛谷P2051] [AHOI2009]中国象棋

    洛谷题目链接:[AHOI2009]中国象棋 题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法 ...

  5. 洛谷 P2051 [AHOI2009]中国象棋 状态压缩思想DP

    P2051 [AHOI2009]中国象棋 题意: 给定一个n*m的空棋盘,问合法放置任意多个炮有多少种情况.合法放置的意思是棋子炮不会相互打到. 思路: 这道题我们可以发现因为炮是隔一个棋子可以打出去 ...

  6. Luogu P2051 [AHOI2009]中国象棋(dp)

    P2051 [AHOI2009]中国象棋 题面 题目描述 这次小可可想解决的难题和中国象棋有关,在一个 \(N\) 行 \(M\) 列的棋盘上,让你放若干个炮(可以是 \(0\) 个),使得没有一个炮 ...

  7. BZOJ1801:[AHOI2009]中国象棋——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=1801 https://www.luogu.org/problemnew/show/P2051 这次小 ...

  8. DP【p2051(bzoj 1801)】 [AHOI2009]中国象棋.

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

  9. LG_2051_[AHOI2009]中国象棋

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

  10. P2051 [AHOI2009]中国象棋

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

随机推荐

  1. mysql数据库基本操作(五)

    表纪录之查(单表查询)2 上一篇讲了4类查询的方式,现在接着上一篇继续看还有哪些方式. group by 分组查询 顾名思义,分组查询要分组,因为mysql5.7之后默认不支持group by语句,需 ...

  2. 如何优雅地停止Java进程

    目录 理解停止Java进程的本质 应该如何正确地停止Java进程 如何注册关闭钩子 使用关闭钩子的注意事项 信号量机制 总结 理解停止Java进程的本质 我们知道,Java程序的运行需要一个运行时环境 ...

  3. Codeforces - 559B - Equivalent Strings - 分治

    http://codeforces.com/problemset/problem/559/B 这个题目,分治就好了,每次偶数层可以多一种判断方式,判断它的时间就是logn的(吧),注意奇数层并不是直接 ...

  4. 安装 statconn 使R与c#交互

    很久以前完成过,但是最近重新折腾发现全忘了,所以记下来. 1.安装 R 2.安装 R studio 3.去 http://rcom.univie.ac.at/download.html 下载 stat ...

  5. bzoj 4407: 于神之怒加强版【莫比乌斯反演+线性筛】

    看着就像反演,所以先推式子(默认n<m): \[ \sum_{d=1}^{n}d^k\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)==d] \] \[ =\sum_{d=1} ...

  6. bzoj 4503: 两个串【脑洞+FFT】

    真实脑洞题 因为通配符所以导致t串实际有指数级别个,任何字符串相关算法都没有用 考虑一个新的匹配方法:设a串(模板串)长为n,从m串的i位置开始匹配:\( \sum_{i=0}^{n-1}(a[j]- ...

  7. noip 2018 Day2 T1 旅行

    暴力删边,暴力枚举 #include <bits/stdc++.h> using namespace std; #define MAXM 5010 inline int read() { ...

  8. Invitation Cards POJ 1511 SPFA || dij + heap

    http://poj.org/problem?id=1511 求解从1去其他顶点的最短距离之和. 加上其他顶点到1的最短距离之和. 边是单向的. 第一种很容易,直接一个最短路, 然后第二个,需要把边反 ...

  9. Ionic开发-如何在ion-content形成上下结构 上面固定下层可滚动

    在一个系统设计中,一般有些需要固定位置,便利操作.现在我要做一个上下两层,需要固定上方,下方拉刷新数据. 页面: <ion-content scroll="false"> ...

  10. sql server的一个字符串分割的表值函数方法

    ALTER function [dbo].[BOSplit](@SourceSql nvarchar(max),  --要分割的字段@StrSeprate varchar(10)      --分割符 ...