[AHOI2009]中国象棋
题目描述
这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法。大家肯定很清楚,在中国象棋中炮的行走方式是:一个炮攻击到另一个炮,当且仅当它们在同一行或同一列中,且它们之间恰好 有一个棋子。你也来和小可可一起锻炼一下思维吧!
输入输出格式
输入格式:
一行包含两个整数N,M,之间由一个空格隔开。
输出格式:
总共的方案数,由于该值可能很大,只需给出方案数模9999973的结果。
输入输出样例
1 3
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 }