P2051 [AHOI2009] 中国象棋 题解
DP好题?
首先确定,每一行/列只能放至多两个棋子,这么少,所以我们的状态肯定和棋子数有关。
由于我们不关注具体的方案数,所以我们不妨只关心对应棋子数量的行/列的数量。同时,由于考虑行和列都是一样的,所以我们不妨用行递推。
所以我们设
容易写出转移方程如下:
一、 若不放棋子
- 直接继承
二、 若放一个棋子
-
若放在有零个棋子的列
放在有零个棋子的列,那么现在和原来相比多了一个有一个棋子的列,所以 ,而放在任意一个零列都可以,所以要乘 。 -
若放在有一个棋子的列
因为你放在有一个棋子的列,有一个棋子的列的数量就减一了,所以对应转移过来应该是加一,而放在这 列都可以,所以要乘 。
三、若放两个棋子
-
若一个放在零个棋子的列,一个放在一个棋子的列
这样就会让两个棋子的列多出一个,所以 ,而放在零个棋子的列有 ,放在一个棋子的列有 ,所以相乘。 -
若两个都放在一个棋子的列
这 个地方都可以选,放两个。 -
若两个都放在零个棋子的列
同上。
再多显然不可能了。
讨论结束。
Code
#include<bits/stdc++.h>
using namespace std;
const int mod=9999973;
int n,m;
long long dp[105][105][105];
long long ans;
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;k<=m-j;++k){
dp[i][j][k]=dp[i-1][j][k]%mod;
if(j>=1) dp[i][j][k]+=dp[i-1][j-1][k]*(m-j-k+1)%mod,dp[i][j][k]%=mod;
if(k>=1) dp[i][j][k]+=dp[i-1][j+1][k-1]*(j+1)%mod,dp[i][j][k]%=mod;
if(k>=1) dp[i][j][k]+=(dp[i-1][j][k-1]*(m-j-k+1)%mod)*j%mod,dp[i][j][k]%=mod;
dp[i][j][k]+=dp[i-1][j+2][k-2]*(j+2)*(j+1)/2%mod,dp[i][j][k]%=mod;
if(j>=2) dp[i][j][k]+=dp[i-1][j-2][k]*(m-j-k+2)*(m-j-k+1)/2%mod,dp[i][j][k]%=mod;
}
}
}
for(int i=0;i<=m;++i){
for(int j=0;j<=m;++j) ans+=dp[n][i][j],ans%=mod;
}
printf("%lld",ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具