引用题解:














#include <cstdio>
#define maxn 105
#define mod 9999973
#define ll long long
using namespace std;
ll n,m,dp[maxn][maxn][maxn],ans;
int C(int num){
return (num*(num-1)/2)%mod;
}
int main(){
scanf("%lld%lld",&n,&m);
dp[0][0][0]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<=m;j++){
for(int k=0;k<=m-j;k++){
dp[i][j][k]=dp[i-1][j][k];//当前行 一颗棋子都不放
if(k>=1)dp[i][j][k]+=dp[i-1][j+1][k-1]*(j+1);//在 放了一个棋子的列 放一个棋子 使当前列 变成有两个棋子的列
if(j>=1)dp[i][j][k]+=dp[i-1][j-1][k]*(m-j-k+1);//在 没有放棋子的列 放一个棋子
/*
为何是m-j-k+1呢
因为剩下 可以选择的列是m-j-k+1 ,当前的j 表示已经在没有棋子的列 放了一个棋子后 产生的
m-j-k 表示 在 没有棋子的一列 放了一个棋子之后 还有多少空着的列
m-j-k+1 则在上面的基础上 多了一列空闲列 ,也就是 上一步的 推过来 还没有 具体操作
*/
if(k>=2)dp[i][j][k]+=dp[i-1][j+2][k-2]*((j+2)*(j+1)/2);//分别在有一个棋子的两列 各放置一个棋子
if(k>=1)dp[i][j][k]+=dp[i-1][j][k-1]*j*(m-j-k+1);//在有一个棋子的一列放一个棋子,再在没有棋子的一列放已给棋子
if(j>=2)dp[i][j][k]+=dp[i-1][j-2][k]*C(m-j+2-k);// 分别在没有棋子的两列 各放置一个棋子
dp[i][j][k]%=mod;
}
}
}
//printf("%d",dp[1][2][0]); 样例 是 dp[1][0][0]+dp[1][1][0]+dp[1][2][0] = 1 + 3 + 3
for(int i=0;i<=m;i++)
for(int j=0;j<=m;j++)
(ans+=dp[n][i][j])%=mod;
printf("%lld",(ans+mod)%mod);
return 0;
}