题目大意:给定一个$n imes 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 ", ans); return 0; }