bzoj 1081 [Ahoi2009] chess 中国象棋

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1801

状态比较难设,的确没想到.

不关心第几列出现是否出现了棋子的个数.而是看看上一行第几列出现了1或2个棋子

利用组合巧妙解决问题.

设\(f[i][j][k]\)表示第i行有j列有1个棋子.有k行有2个棋子.

那么为空的即为\(m - j - k\)

状态转移方程:

1.这一行什么都不放:

\(f[i][j][k] += f[i - 1][j][k]\)

2.这一行放一个 在空行上放

\(f[i][j][k] += f[i - 1][j - 1][k] * (m - (j - 1) - k);\)

3.这一行放一个 在有一个棋子放

\(f[i][j][k] += f[i - 1][j + 1][k - 1] * (j + 1);\)

4.这一行放两个 都在一个棋子上放

\(f[i][j][k] += f[i - 1][j + 2][k - 2] * C(j + 2,2);\)

5.这一行放两个 在没有棋子上面放

\(f[i][j][k] += f[i - 1][j - 2][k] * C(m - j - k + 2,2);\)

6.这一行一个棋子在一个棋子的列上放,一个棋子在没有棋子的列上方

\(f[i][j][k] += f[i - 1][j][k - 1] * j * (m - j - k + 1)\)

边界的话:当然是\(f[0][0][0] = 1\)啦

滚动一下数组非常快

/*
卡常记录 :
总耗时 : 111ms -> 86ms
最高用时 : 23ms -> 17ms
*/
#include <iostream>
#include <cstdio>
#define rep(i,x,p) for(register int i = x;i <= p;++ i)
#define sep(i,x,p) for(register int i = x;i >= p;-- i)
#define gc getchar()
#define pc putchar
const int maxN = 100 + 7;
const int mod = 9999973; long long f[2][maxN][maxN];
int n,m; inline int read() {
int x = 0,f = 1;char c = gc;
while(c < '0' || c > '9') {if(c == '-')f = -1;c = gc;}
while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = gc;}
return x * f;
} inline int C(int n) {
return n * ( n - 1 ) / 2;
} int main() {
f[0][0][0] = 1;
int n,m;
n = read();m = read();
rep(i,1,n) {
int x = i % 2,q = x ? 0 : 1;
rep(j , 0 , m) {
for(register int k = 0;k + j <= m;++ k) {
f[x][j][k] = f[q][j][k];
if(j >= 1) f[x][j][k] += f[q][j - 1][k] * (m - (j - 1) - k);
if(k >= 1) f[x][j][k] += f[q][j + 1][k - 1] * (j + 1);
if(k >= 2) f[x][j][k] += f[q][j + 2][k - 2] * C(j + 2);
if(j >= 2) f[x][j][k] += f[q][j - 2][k] * C(m - j - k + 2);
if(k >= 1) f[x][j][k] += f[q][j][k - 1] * j * (m - j - k + 1);
f[x][j][k] %= mod;
}
}
}
long long ans = 0,x = n % 2;
rep(j , 0 , m) {
for(register int k = 0;k + j <= m;++ k)
ans += f[x][j][k];
ans %= mod;
}
printf("%lld\n", ans);
return 0;
}

Bzoj 1081 [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 中国象棋

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

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

    题目链接:BZOJ - 1801 题目分析 对于50%的数据是可以直接状压 DP 的. 对于100%的数据,使用递推的 DP .(或者这只叫递推不叫 DP ?) 可以发现,每一行和每一列的棋子个数不能 ...

  4. BZOJ 1801: [Ahoi2009]chess 中国象棋 [DP 组合计数]

    http://www.lydsy.com/JudgeOnline/problem.php?id=1801 在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮. 请问有多少种放 ...

  5. bzoj 1801: [Ahoi2009]chess 中国象棋【dp】

    注意到一行只能放012个炮,我们只需要知道列的状态,不用状压行 所以设f[i][j][k]表示前i行有j列有1个炮,有k列有2个炮的方案数 然后分情况讨论转移就行了 #include<cstdi ...

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

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

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

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

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

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

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

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

随机推荐

  1. nginx大量TIME_WAIT的解决办法

    1.netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' 查看time_wait 很大 2.解决此问题需要对sysc ...

  2. 【JavaScript权威指南】——逻辑与(&&)

    三种用法总结: 1.布尔值计算: [成员]={false,true} 2.“真值”,“假值”计算: [假值]={false,null,undefined,0,-0,NaN,""} ...

  3. 洛谷P5280 [ZJOI2019]线段树

      https://www.luogu.org/problemnew/show/P5280 省选的时候后一半时间开这题,想了接近两个小时的各种假做法,之后想的做法已经接近正解了,但是有一些细节问题理不 ...

  4. FileChannel与ByteBuffer的使用示例

    DirectByteBuffer直接内存的使用场景和作用 生命周期长的大对象, 减少java堆GC, 减少内存copy http://www.importnew.com/26334.html publ ...

  5. 设计模式——单例模式(Singleton)

    保证一个类仅有一个实例,并提供一个访问它的全局访问点.——DP UML类图 模式说明 个人认为单例模式是所有设计模式中最为简单的一个模式,因为实现这个模式仅需一个类,而不像其他模式需要若干个类.这个模 ...

  6. GUI的最终选择 Tkinter(四):Entry、Listbox、Scrollbar和Scale组件

    Entry组件 Entry组件就是平时所说的输入框.输入框是程序员用到的最多的一个程序,例如在输入账号和密码的时候需要提供两个输入框,用于接收密码的输入框还会有星号将实际输入的内容隐藏起来. Tkin ...

  7. Java面向对象_常用类库api——二叉树数据结构实现

    二叉树是每个节点最多有两个子树的有序树.通常子树被称为"左子树"和"右子树". 二叉树算法的排序规则: 1.选择第一个元素作为根节点 2.之后如果元素大于根节点 ...

  8. JDBC连接数据库(Servlet+JSP)

    JDBC(Java Database connectivity),是连接数据库的一种方式.后面的框架Mybatis和Hibernate等都封装的是JDBC.在JDBC中常用的API有4个:Driver ...

  9. C#值类型、引用类型的区别

    在<C#类型简述>http://blog.csdn.net/letnet1981/article/details/48223831,中提到了值类型和引用类型,这里我们就来了解一下它们的区别 ...

  10. iOS核心动画高级技巧之图层变换和专用图层(二)

    iOS核心动画高级技巧之CALayer(一) iOS核心动画高级技巧之图层变换和专用图层(二)iOS核心动画高级技巧之核心动画(三)iOS核心动画高级技巧之性能(四)iOS核心动画高级技巧之动画总结( ...