P2051 [AHOI2009]中国象棋

状压 dp。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int p = 9999973;
int f[105][105][105];
int C(int x)
{
	return (x * (x - 1) / 2) % p;
}
signed main()
{
	int n, m;
	scanf("%lld%lld", &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; j + k <= m && j + k <= 2 * i; k++)
			{
				f[i][j][k] = (f[i][j][k] + f[i - 1][j][k]) % p;
				if(j >= 1)
				{
					f[i][j][k] = (f[i][j][k] + f[i - 1][j - 1][k] * (m - j - k + 1) % p) % p;
				}
				if(k >= 1)
				{
					f[i][j][k] = (f[i][j][k] + f[i - 1][j + 1][k - 1] * (j + 1) % p) % p;
				}
				if(j >= 2)
				{
					f[i][j][k] = (f[i][j][k] + f[i - 1][j - 2][k] * C(m - j - k + 2) % p) % p;
				}
				if(k >= 1)
				{
					f[i][j][k] = (f[i][j][k] + f[i - 1][j][k - 1] * j % p * (m - j - k + 1) % p) % p;
				}
				if(k >= 2)
				{
					f[i][j][k] = (f[i][j][k] + f[i - 1][j + 2][k - 2] * C(j + 2) % p) % p;
				}
			}
		}
	}
	int ans = 0;
	for(int j = 0; j <= m; j++)
	{
		for(int k = 0; j + k <= m && j + k <= 2 * n; k++)
		{
			ans += f[n][j][k];
			ans %= p;
		}
	}
	printf("%lld", ans);
	return 0;
}