[AHOI2009]中国象棋

每行每列最多放两个
dp 数组记录第i 行,有j 列放了1个,k 列放了2个的方案数
不放

放一个

放两个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<cstdio>
#define LL long long
const int N=105,mod=9999973;
int n,m;
LL dp[N][N][N]; //row,1,2
int main()
{
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;j+k<=m;k++)
{
dp[i][j][k]=(dp[i][j][k]+dp[i-1][j][k])%mod;
if (m-j-k>0) dp[i][j+1][k]=(dp[i][j+1][k]+dp[i-1][j][k]*(m-j-k))%mod;
if (j>0) dp[i][j-1][k+1]=(dp[i][j-1][k+1]+dp[i-1][j][k]*j)%mod;
if (j>=2) dp[i][j-2][k+2]=(dp[i][j-2][k+2]+dp[i-1][j][k]*j*(j-1)/2)%mod;
if (m-j-k>=2) dp[i][j+2][k]=(dp[i][j+2][k]+dp[i-1][j][k]*(m-j-k)*(m-j-k-1)/2)%mod;
if (j>0&&m-j-k>0) dp[i][j][k+1]=(dp[i][j][k+1]+dp[i-1][j][k]*(m-j-k)*j)%mod;
}
int ans=0;
for(int i=0;i<=m;i++)
for(int j=0;i+j<=m;j++)
ans=(ans+dp[n][i][j])%mod;
printf("%d\n",ans);
return 0;
}