【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;
}