[AHOI2009]中国象棋

题目描述

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

输入输出格式

输入格式:

一行包含两个整数N,M,之间由一个空格隔开。

输出格式:

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

 

输入输出样例

输入样例#1:
1 3
输出样例#1:
7

说明

样例说明

除了3个格子里都塞满了炮以外,其它方案都是可行的,所以一共有2*2*2-1=7种方案。

数据范围

100%的数据中N和M均不超过100

50%的数据中N和M至少有一个数不超过8

30%的数据中N和M均不超过6

F[I][J][K] 表示已经放了前I行,其中有J列是只放了1个炮,有K列放了2个炮的方案数

有: 1〉如果第I行不放,有

F[i][J][K]:=F[I][J][K]+F[I-1][J][K];

2〉如果第I行放一个棋子,且这个棋子放在已经放了一个棋子的列上,有

F[I][J][K]:=F[I][J][K]+F[I-1][J+1][K-1]*(J+1);

3〉如果第I行放一个棋子,且这个棋子放在已放了0个棋子的列上,有:

F[I][J][K]:=F[I][J][K]+F[I-1][J-1][K]*(M-J-K+1);

4〉如果第I列放两个棋子,且两个棋子都放在空列上,有:

F[I][J][K]:=F[I][J][K]+F[i-1][J-2][K]*(M-J+2-K);

5〉如果第I列放两个棋子,且两个棋子一个放在已经放了一个棋子的列,另一个放在放了0个棋子的列。有

F[I][J][K]:=F[I][J][K]+F[I-1][J+2][K-2]*(J+2)*(J+1)DIV 2 ;

6〉如果第I列放两个棋子,且这两个棋子都放在已经放过1个棋子的列上,有:

F[I][J][K]:=F[I][J][K]+F[I-1][J][K-1]*J*(M-J-K+1);

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 using namespace std;
 6 typedef long long lol;
 7 int Mod=9999973;
 8 lol f[101][101][101],ans;
 9 lol n,m;
10 int main()
11 {lol i,j,k;
12     cin>>n>>m;
13     f[0][0][0]=1;
14     for (i=0;i<n;i++)
15     {
16         for (j=0;j<=m;j++)
17         {
18             for (k=0;j+k<=m;k++)
19             if (f[i][j][k])
20             {
21                 f[i+1][j][k]=(f[i+1][j][k]+f[i][j][k])%Mod;
22                 if (j>=1)
23                 f[i+1][j-1][k+1]=(f[i+1][j-1][k+1]+f[i][j][k]*j)%Mod;
24                 if (m-j-k>=1)
25                 f[i+1][j+1][k]=(f[i+1][j+1][k]+f[i][j][k]*(m-j-k))%Mod;
26                 if (j>=2)
27                 f[i+1][j-2][k+2]=(f[i+1][j-2][k+2]+f[i][j][k]*(j-1)*j/2)%Mod;
28                 if (m-j-k>=2)
29                 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;
30                 if (m-j-k>=1&&j>=1)
31                 f[i+1][j][k+1]=(f[i+1][j][k+1]+f[i][j][k]*(m-j-k)*j)%Mod;
32             }
33         }
34     }
35     for (i=0;i<=m;i++)
36     for (j=0;j+i<=m;j++)
37       ans=(ans+f[n][i][j])%Mod;
38     cout<<(ans+Mod)%Mod;
39 } 

 

posted @ 2017-08-09 12:11  Z-Y-Y-S  阅读(224)  评论(0编辑  收藏  举报