【P2051】中国象棋

题意

求有多少种棋盘使得每一列和每一行的棋子个数不超过 \(2\) 个。

思路

设计 \(f_{i,j,k}\) 表示前 \(i\) 行,有 \(j\) 列为 \(1\) 个棋子,\(k\) 列为 \(0\) 个棋子。

  • 考虑当前行放 \(0\) 个棋子,则有 \(f_{i,j,k} = f_{i-1,j,k}\)
  • 若当前行放 \(1\) 个棋子,一种可能是放在 \(1\) 的列,另一种可能是放在 \(0\) 的列。
  • 若当前行放 \(2\) 个棋子,可以两个都放 \(0\),或者两个都放 \(1\),或者一个放 \(0\) 一个放 \(1\)

对应的情况要乘对应的排列系数,比较显然就不再赘述。

code

#include<bits/stdc++.h>
#define ll long long

using namespace std;

const ll N = 105,mod = 9999973,inv = 4999987;
 
int n,m;
ll dp[N][N][N];
void add(ll &x,ll y){
	(x+=y)%=mod;
}
int main() {
	cin>>n>>m;
	
	ll ans=0;
	dp[0][0][m]=1;
	for(int i=1;i<=n;i++){
		for(int j=0;j<=m;j++){
			for(int k=0;k<=m-j;k++){
				ll &res=dp[i][j][k];
				add(res,dp[i-1][j][k]);
				add(res,dp[i-1][j+1][k]*(j+1)%mod);
				if(j)add(res,dp[i-1][j-1][k+1]*(k+1)%mod);
				if(j>=2)add(res,dp[i-1][j-2][k+2]*(k+2)%mod*(k+1)%mod*inv%mod);
				add(res,dp[i-1][j+2][k]*(j+2)%mod*(j+1)%mod*inv%mod);
//				add(res,dp[i-1][j][k+1]*(k+1)%mod);
				add(res,dp[i-1][j][k+1]*(k+1)%mod*j%mod);
				if(i==n)ans=(ans+res)%mod;
			}
		}
	}
	cout<<ans;
	return 0;
}
posted @ 2025-09-17 20:56  Harvey-zhuhy  阅读(6)  评论(0)    收藏  举报