cychester

Luogu 2051[AHOI2009]中国象棋 - DP

Description

在 $n * m$ 的格子上放若干个炮, 使得每个炮都不能攻击到其他炮

 

Solution

定义数组f[ i ][ j ][ k ] 表示到了第 i 行, 已经有2个炮的列数为 j, 有1个炮的列数 为k, 的方案数有多少。

然后就能非常简单的写个dp了

 

Code

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define ll long long
 5 #define rep(i,a,b) for(int i = (a); i <= (b); ++i)
 6 #define per(i,a,b) for(int i = (a); i >= (b); --i)
 7 #define rd read()
 8 using namespace std;
 9 
10 const int N = 105;
11 const int mod = 9999973;
12 
13 int n, m, op, ans;
14 int f[2][N][N];
15 
16 int read() {
17     int X = 0, p = 1; char c = getchar();
18     for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1;
19     for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0';
20     return X * p;
21 }
22 
23 int C(int a) {
24     return ((a - 1) * a / 2) % mod;
25 }
26 
27 int main()
28 {
29     n = rd; m = rd;
30     f[0][0][0] = 1;
31     rep(i, 1, n) {
32         op ^= 1;
33         rep(j, 0, m) rep(k, 0, m - j) {
34             f[op][j][k] = f[op ^ 1][j][k];
35             if(k >= 1) f[op][j][k] = (f[op][j][k] + 1LL * (m - j - k + 1) * f[op ^ 1][j][k - 1] % mod) % mod;
36             if(j >= 1) f[op][j][k] = (f[op][j][k] + 1LL * (k + 1) * f[op ^ 1][j - 1][k + 1] % mod) % mod;
37             if(k >= 2) f[op][j][k] = (f[op][j][k] + 1LL * C(m - j - k + 2) * f[op ^ 1][j][k - 2] % mod) % mod;
38             if(j >= 1) f[op][j][k] = (f[op][j][k] + 1LL * k * (m - j + 1- k) % mod * f[op ^ 1][j - 1][k] % mod) % mod;
39             if(j >= 2) f[op][j][k] = (f[op][j][k] + 1LL * C(k + 2) * f[op ^ 1][j - 2][k + 2] % mod) % mod;
40         }
41     }
42     rep(i, 0, m) rep(j, 0, m - i) ans = (ans + f[op][i][j]) % mod;
43     ans = (ans % mod + mod) % mod;
44     printf("%d\n", ans);
45 }
View Code

 

posted on 2018-09-02 11:28  cychester  阅读(136)  评论(0编辑  收藏  举报

导航