[bzoj1801][Ahoi2009]chess 中国象棋
题目大意:给定一个$n\times m$的棋盘,问有多少种不同的放置炮的方案使得任意两个炮不能互相攻击。
题解:$f_{i,j,k}$表示到了第$i$行,前面有$j$列有一个炮,有$k$列有两个炮
转移懒得写,见代码
卡点:无
C++ Code:
#include <cstdio>
#define maxn 111
using namespace std;
const int mod = 9999973;
int n, m;
long long f[maxn][maxn][maxn], ans;
long long C(long long a, long long b) {
b %= mod;
if (b == 1) return a % mod;
if (b == 2) return (a * (a - 1) >> 1) % mod;
return 20040826;
}
void up(long long &a, long long b) {
a = (a + b) % mod;
}
int main() {
scanf("%d%d", &n, &m);
f[0][0][0] = 1;
for (int i = 1; i <= m; i++) {
for (int j = 0; j <= n; j++) {
for (int k = 0; k + j <= n; k++) {
long long tmp = f[i - 1][j][k];
if (tmp) {
up(f[i][j][k], tmp);
up(f[i][j + 2][k], tmp * C(n - k - j, 2));
up(f[i][j + 1][k], tmp * C(n - k - j, 1));
up(f[i][j][k + 1], tmp * C(j, 1) % mod * C(n - k - j, 1));
if (j) up(f[i][j - 1][k + 1], tmp * C(j, 1));
if (j > 1) up(f[i][j - 2][k + 2], tmp * C(j, 2));
}
}
}
}
for (int i = 0; i <= n; i++) {
for (int j = 0; i + j <= n; j++) up(ans, f[m][i][j]);
}
printf("%lld\n", ans);
return 0;
}

浙公网安备 33010602011771号