1801: Ahoi2009 chess 中国象棋
Description
在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮。 请问有多少种放置方法,中国像棋中炮的行走方式大家应该很清楚吧.
Input
一行包含两个整数N,M,中间用空格分开.
Output
输出所有的方案数,由于值比较大,输出其mod 9999973
Sample Input
1 3
Sample Output
7
HINT
除了在3个格子中都放满炮的的情况外,其它的都可以.
100%的数据中N,M不超过100
50%的数据中,N,M至少有一个数不超过8
30%的数据中,N,M均不超过6
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
inline void read(int &x){
x=0; int f=1; char c=getchar();
while(c>'9'||c<'0'){ if(c=='-') f=-1; c=getchar(); }
while(c>='0'&&c<='9'){ x=x*10+c-'0'; c=getchar(); } x*=f;
}
#define Mod 9999973
long long f[105][105][105],ans;
#define fijk f[i][j][k]
inline int C(int n){//就是 C(n,2) 组合数
return (n*(n-1)/2)%Mod;
}
//f[i][j][k] 表示前i行 有j列是一个炮 有k列是两个炮
int Main(){
int n,m;
read(n),read(m);
f[0][0][0]=1;
register int i,j,k;
for(i=1;i<=n;++i)
for(j=0;j<=m;++j)
for(k=0;k+j<=m;++k){
fijk=(fijk+f[i-1][j][k])%Mod;
if(k>=1) fijk=(fijk+f[i-1][j+1][k-1]*(j+1))%Mod;//在某列放了一个的下面添一个 j-- ++k 得到现在的状态
if(j>=1) fijk=(fijk+f[i-1][j-1][k]*(m-(j-1)-k))%Mod;//没放过的
if(j>=2) fijk=(fijk+f[i-1][j-2][k]*C(m-k-(j-2)))%Mod;//找两个空列 各方一个泡
if(k>=2) fijk=(fijk+f[i-1][j+2][k-2]*C(j+2))%Mod;//找两个有一个泡的列 各方一个泡
if(k>=1) fijk=(fijk+f[i-1][j][k-1]*j*(m-j-(k-1)))%Mod;//一个空列和一个放了一个棋子的列 各方一个泡
}
for(i=0;i<=m;++i)
for(j=0;j+i<=m;++j)
ans=(ans+f[n][i][j])%Mod;
printf("%I64d\n",ans);
return 0;
}
int Aptal_is_My_Son=Main();
int main(int argc,char *argv[]){ ; }