看代码注释
#include<bits/stdc++.h>
using namespace std;
int n,m;
typedef long long ll;
const ll mod = 9999973;
long long ans = 0;
long long dp[110][110][110];//前i行有j列放了一个炮k列放了两个炮;
int main()
{
cin >> n >> m;
dp[0][0][0] = 1;//初始化一个没放方案数为1;
for(int i = 0; i < n; i++)
for(int j = 0; j <= m; j++)
for(int k = 0; k+j <= m; k++)
if(dp[i][j][k])
{
//i+1行不放棋子
dp[i+1][j][k] = (dp[i+1][j][k] + dp[i][j][k]) % mod;
//i+1行放一个在没炮的列
if(m-j-k >= 1)dp[i+1][j+1][k] = (dp[i+1][j+1][k] + dp[i][j][k]*(m-k-j)) % mod;
//i+1行放一个在有一个炮的列
if(j >= 1)dp[i+1][j-1][k+1] = (dp[i+1][j-1][k+1] + dp[i][j][k]*j) % mod;
//i+1行在没有炮的两列各放一个
if(m-j-k >= 2)dp[i+1][j+2][k] = (dp[i][j][k]*((m-j-k)*(m-j-k-1)/2) + dp[i+1][j+2][k]) % mod;
//i+1行在没有炮的一列和有一个炮的一列各放一个
if(m-j-k >= 1&&j >= 1)dp[i+1][j][k+1] = (dp[i+1][j][k+1] + dp[i][j][k]*j*(m-j-k)) % mod;
//i+1行1在有一个炮的两列各放一个
if(j >= 2)dp[i+1][j-2][k+2] = (dp[i+1][j-2][k+2] + dp[i][j][k]*((j*(j-1))/2)) % mod;
}
for(int i = 0; i <= m; i++)
for(int j = 0; j+i <= m;j++)
ans = (ans+dp[n][i][j])%mod;
cout << ans;
return 0;
}