dp(r,i,j)表示第r行有0个炮的列数为i,有1个炮的列数为j,有2个炮的列数为m-i-j时的情况数
决策有三个,当前行放0个炮,放1个炮,放2个炮
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 110; const int mod = 999983; typedef long long ll; int n, m; ll dp[maxn][maxn][maxn]; void solve() { memset(dp, 0, sizeof(dp)); dp[0][m][0] = 1; for (int r = 0; r < n; r++) { for (int i = 0; i <= m; i++) { for (int j = 0; j + i <= m; j++) { if (!dp[r][i][j]) continue; dp[r+1][i][j] = (dp[r+1][i][j] + dp[r][i][j]) % mod; if (i >= 1) dp[r+1][i-1][j+1] = (dp[r+1][i-1][j+1] + dp[r][i][j] * i) % mod; if (j >= 1) dp[r+1][i][j-1] = (dp[r+1][i][j-1] + dp[r][i][j] * j) % mod; if (i >= 2) dp[r+1][i-2][j+2] = (dp[r+1][i-2][j+2] + dp[r][i][j] * i * (i - 1) / 2) % mod; if (i >= 1) dp[r+1][i-1][j] = (dp[r+1][i-1][j] + dp[r][i][j] * i * j) % mod; if (j >= 2) dp[r+1][i][j-2] = (dp[r+1][i][j-2] + dp[r][i][j] * j * (j - 1) / 2) % mod; } } } } int main() { while (~scanf("%d%d", &n, &m)) { solve(); int ans = 0; for (int i = 0; i <= m; i++) { for (int j = 0; j + i <= m; j++) { ans = (ans + dp[n][i][j]) % mod; } } printf("%d\n", ans); } return 0; }