https://www.luogu.org/problem/P2051
总共分为3种情况:
1.放0个棋子: 直接转移
2.放1个棋子: 将一颗棋子放在已含有0个棋子的列中
将一颗棋子放在已含有1个棋子的列中
3.放2个棋子: 将两颗棋子放在已含有1个棋子的列中
将两颗棋子放在已含有0个棋子的列中
将两颗棋子放在各含有0个棋子和1个棋子的列中
转移的过程中要注意边界的判定
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 9999973
ll dp[105][105][105];
ll cal(ll n){
n=(n*(n-1)/2)%mod;
return n;
}
ll max(ll a,ll b){
return a>b?a:b;
}
int main(){
int n,m;
scanf("%d%d",&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;k++){
if((m-j-k)<0)break;
dp[i][j][k]=dp[i-1][j][k];
if(j>=1)dp[i][j][k]+=dp[i-1][j-1][k]*(m-j+1-k);
if(k>=1)dp[i][j][k]+=dp[i-1][j+1][k-1]*(j+1);
if(k>=2)dp[i][j][k]+=dp[i-1][j+2][k-2]*cal(j+2);
if(j>=2)dp[i][j][k]+=dp[i-1][j-2][k]*cal(m-j-k+2);
if(k>=1)dp[i][j][k]+=dp[i-1][j][k-1]*(m-j-k+1)*j;
dp[i][j][k]%=mod;
}
}
}
ll ans=0;
for(int i=0;i<=m;i++){
for(int j=0;j<=m;j++){
ans+=dp[n][i][j];
ans%=mod;
}
}
printf("%d\n",ans);
return 0;
}