题目描述
//每行每列最多放两个,可以讨论第i-1行到第i行的每一种情况
#include<complex>
#include<cstdio>
using namespace std;
const int mod=9999973;
const int N=101;
int n,m;
long long f[N][N][N];
//f[i][j][k]表示前i行有j列放了一个,k列放了两个按方案数
int qread()
{
int x=0;
char ch=getchar();
while(ch<'0' || ch>'9')ch=getchar();
while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x;
}
void Add(long long &x,long long y)
{
x+=y;
if(x>=mod)x%=mod;
}
int main()
{
scanf("%d%d",&n,&m);
f[0][0][0]=1;
for(int i=1;i<=n;i++)
for(int j=0;j<=m;j++)
for(int k=0;k+j<=m;k++)
{
f[i][j][k]=f[i-1][j][k];//不放
if(j)Add(f[i][j][k],f[i-1][j-1][k]*(m-k-j+1));//放一个在没有棋子的列
if(k)Add(f[i][j][k],f[i-1][j+1][k-1]*(j+1));//放一个在有一个棋子的列
if(k>=2)Add(f[i][j][k],f[i-1][j+2][k-2]*(j+2)*(j+1)>>1);//放两个在有一个棋子的列
if(j>=2)Add(f[i][j][k],f[i-1][j-2][k]*(m-k-j+2)*(m-k-j+1)>>1);//放两个在没有棋子的列
if(j && k)Add(f[i][j][k],f[i-1][j][k-1]*(m-k-j+1)*j);//放一个在没有棋子的列,另一个在有一个棋子的列
}
long long ans=0;
for(int i=0;i<=m;i++)
for(int j=0;j+i<=m;j++)
Add(ans,f[n][i][j]);
printf("%d
",ans);
return 0;
}