【题目大意】

叫你在\(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】

  1. #pragma GCC optimize("O3")
  2. #pragma GCC optimize("O2")
  3. #include<cstdio>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #define ll long long
  7. #define R register
  8. using namespace std;
  9. const int MAX = 100 + 5;
  10. const int mod = 9999973;
  11. inline int read(){
  12. int f = 1, x = 0;char ch;
  13. do { ch = getchar(); if (ch == '-') f = -1; } while (ch < '0'||ch>'9');
  14. do {x = x*10+ch-'0'; ch = getchar(); } while (ch >= '0' && ch <= '9');
  15. return f*x;
  16. }
  17. inline ll c(ll x) {
  18. return (x * (x - 1) / 2) % mod;
  19. }
  20. int n, m;
  21. ll f[MAX][MAX][MAX], ans;
  22. int main(){
  23. n = read(), m = read();
  24. f[0][0][0] = 1;
  25. for (R int i = 1;i <= n; ++i) {
  26. for (R int j = 0;j <= m; ++j) {
  27. for (R int k = 0;k <= m - j; ++k) {
  28. f[i][j][k] = f[i-1][j][k];
  29. if (k > 0) {
  30. f[i][j][k] += (f[i-1][j+1][k-1] * (j+1)) % mod;
  31. f[i][j][k] %= mod;
  32. f[i][j][k] += (f[i-1][j][k-1] * j * (m-j-k+1)) %mod;
  33. f[i][j][k] %= mod;
  34. }
  35. if (j > 0) {
  36. f[i][j][k] += (f[i-1][j-1][k] * (m-j-k+1)) %mod;
  37. f[i][j][k] %= mod;
  38. }
  39. if (k > 1) {
  40. f[i][j][k] += (f[i-1][j+2][k-2] * c(j+2)) % mod;
  41. f[i][j][k] %= mod;
  42. }
  43. if (j > 1) {
  44. f[i][j][k] += (f[i-1][j-2][k] * c(m-j-k+2)) % mod;
  45. f[i][j][k] %= mod;
  46. }
  47. }
  48. }
  49. }
  50. for (R int i = 0;i <= m; ++i) {
  51. for (R int j = 0;j <= m; ++j) {
  52. ans += f[n][i][j];
  53. ans %= mod;
  54. }
  55. }
  56. printf("%lld", (ans + mod) % mod);
  57. return 0;
  58. }

【简●解】[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. C++章节练习题

    笔试宝典:http://www.bishibaodian.com/writtenCircle/lightquestionlist http://www.bishibaodian.com/written ...

  2. POJ1017 【据说是贪心...】

    题意: 有6种面积的格子,给出这些格子的数量,然后有6*6的格子去容纳这6种面基,问最少需要几个6*6格子,使得所有类型的小格子被容纳. 思路: 按照面积的从大到小放. 一开始还是太天真,还要用各种1 ...

  3. Cg(C for Graphic)语言表达式与控制语句(转)

    摘抄“GPU Programming And Cg Language Primer 1rd Edition” 中文名“GPU编程与CG语言之阳春白雪下里巴人” 在上一章中,我们已经介绍了 Cg 语言的 ...

  4. linux 读取部分文件内容

    一般我们在linux上读取文件,是用vi工具,如果是写shell 脚本时,一般式通过cat 再 使用管道来达到流的处理. 但如果文件太大,单纯的cat 可能会使用过多的内存,而且实现上还需要后续的加工 ...

  5. 用jquery的animate动画函数做的网页效果

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. 并查集 HDOJ 5441 Travel

    题目传送门 题意:给一张无向图,问存在多少(a, b)表示a点到b点经过的边值小于等于x ((a,b) 和 (b, a)属于不同的方案) 分析:首先将边权值和查询x值升序排序,从前往后扫描边,累加从u ...

  7. Codeforces Round #295 (Div. 2) B. Two Buttons

    B. Two Buttons time limit per test 2 seconds memory limit per test 256 megabytes input standard inpu ...

  8. magento layout xml 小结

    基础概念: http://magebase.com/magento-tutorials/demystifying-magentos-layout-xml-part-1/ 调试方案函数: $this-& ...

  9. Android应用的安全隐患*

    转自: http://www.cnblogs.com/chi0591/p/3864747.html Android应用的安全隐患包括三个方面: 代码安全 数据安全 组件安全 代码安全 代码安全主要是指 ...

  10. Android Studio编译开源项目(含NDK开发)常见报错

    1.未设置NDK的路径 Error:Execution failed for task ':library:ndkBuild'. > A problem occurred starting pr ...