jzoj P1667 【AHOI2009】中国象棋

127 篇文章 0 订阅
11 篇文章 0 订阅

题目大意:
在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮。求有多少种放置方法?由于值比较大,输出其mod 9999973的结果。
中国象棋中炮的行走方式大家应该很清楚吧。

100%的数据中N,M不超过100
50%的数据中,N,M至少有一个数不超过8
30%的数据中,N,M均不超过6

题解:
DP:
题目可以发现,每一列最多放2个炮,所以可以做动规:
f[i,j,k]表示前i行j列放1个棋,k列放2个棋子的最大值。
所以对于到f[i,j,k]有6个情况:
1.不放棋子丨f[i-1][j][k]
2.放一个棋子,放在之前没有棋子的一列丨f[i-1][j-1][k]*(m-j-k+1)
3.放一个棋子,放在之前有一个棋子的一列丨f[i-1][j+1][k-1]*(j+1);
4.放两个棋子,放在之前没有棋子的两列丨f[i-1][j-2][k]*C(m-j-k+2)
5.放两个棋子,都放在之前没有棋子的一列丨f[i-1][j][k-1]*(m-j-k+1)*j
6.放两个棋子,分别放在之前没有棋子和有一个棋子的两列丨f[i-1][j+2][k-2]*C(j+2)
C的操作是x*(x-1) div 2,这是某个很神奇的组合数操作….

var
     f:array [-10..101,-10..101,-10..101] of longint;
     ans,n,m,i,j,k:longint;

function c(a:longint):longint;
begin
      exit(a*(a-1) div 2);
end;

begin
     readln(n,m);
     f[0,0,0]:=1;
     for i:=1 to n do
         for j:=0 to m do
             for k:=0 to m-j do
                 begin
                       f[i,j,k]:=(f[i-1,j,k]+
                                  f[i-1,j-1,k]*(m-j-k+1)+
                                  f[i-1,j+1,k-1]*(j+1)+
                                  f[i-1,j-2,k]*c(m-j-k+2)+
                                  f[i-1,j,k-1]*(m-j-k+1)*j+
                                  f[i-1,j+2,k-2]*c(j+2)) mod 9999973;
                 end;
     for i:=0 to m do
         for j:=0 to m-i do
             ans:=(ans+f[n,i,j]) mod 9999973;
     writeln(ans);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值