P2051 [AHOI2009] 中国象棋题解

P2051 [AHOI2009] 中国象棋

题目描述

这次小可可想解决的难题和中国象棋有关,在一个 nnnmmm 列的棋盘上,让你放若干个炮(可以是 000 个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法。大家肯定很清楚,在中国象棋中炮的行走方式是:一个炮攻击到另一个炮,当且仅当它们在同一行或同一列中,且它们之间恰好 有一个棋子。你也来和小可可一起锻炼一下思维吧!

输入格式

一行包含两个整数 n,mn,mn,m,之间由一个空格隔开。

输出格式

总共的方案数,由于该值可能很大,只需给出方案数模 999997399999739999973 的结果。

输入输出样例 #1

输入 #1

1 3

输出 #1

7

说明/提示

样例说明

除了 333 个格子里都塞满了炮以外,其它方案都是可行的,所以一共有 2×2×2−1=72 \times 2 \times 2-1=72×2×21=7 种方案。

数据规模与约定

  • 对于 30%30\%30% 的数据,nnnmmm 均不超过 666
  • 对于 50%50\%50% 的数据,nnnmmm 至少有一个数不超过 888
  • 对于 100%100\%100% 的数据,1≤n,m≤1001 \leq n,m \leq 1001n,m100

题面修改:@syksykCCC。

思路

DP即可。

代码见下

#include<bits/stdc++.h>
#define mod 9999973
using namespace std;
long long n,m,f[105][105][105],op=0;
int main(){
    cin>>n>>m;
    f[0][0][0]=1;
    for(int i=0;i<=n-1;i++){
        for(int j=0;j<=m;j++){
            for(int k=0;k+j<=m;k++){
                if(j>=1){
                    f[i+1][j-1][k+1]=(f[i+1][j-1][k+1]+f[i][j][k]*j)%mod;
                }
                if(m-j-k>=1){
                    f[i+1][j+1][k]=(f[i+1][j+1][k]+f[i][j][k]*(m-j-k))%mod;
                }
                if(j>=2){
                    f[i+1][j-2][k+2]=(f[i+1][j-2][k+2]+f[i][j][k]*j*(j-1)/2)%mod;
                }
                if(m-j-k>=2){
                    f[i+1][j+2][k]=(f[i+1][j+2][k]+f[i][j][k]*(m-j-k)*(m-j-k-1)/2)%mod;
                }
                if(m-j-k>=1&&j>=1){
                    f[i+1][j][k+1]=(f[i+1][j][k+1]+f[i][j][k]*(m-j-k)*j)%mod;
                }
                f[i+1][j][k]=(f[i+1][j][k]+f[i][j][k])%mod;
            }
        }
    }
    op=0;
    op=0;
    for(int i=0;i<=m;i++){
        for(int j=0;j+i<=m;j++){
            op=(op+f[n][i][j])%mod;
        }
    }
    cout<<op<<endl;
	return 0;
}
posted @ 2025-11-17 21:26  bz02_2023f2  阅读(2)  评论(0)    收藏  举报  来源