bzoj 1801: [Ahoi2009]chess 中国象棋 (组合数+DP)

来源:互联网 发布:谁在淘宝上买过精密管 编辑:程序博客网 时间:2024/05/22 12:45

题目描述

传送门

题目大意:在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮。 请问有多少种放置方法。(ps:炮必须是隔一个打一个)

题解

转述一下题意就是:每行每列最多选2个位置的方案数。
f[i][j][k]表示到第i行,有j列有0个数,k列有1个数的方案数。

代码

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#define p 9999973#define N 103#define LL long long using namespace std;int n,m,f[N][N][N],c[N][N];int main(){    freopen("a.in","r",stdin);    scanf("%d%d",&n,&m);    int t=max(n,m);    for (int i=0;i<=t;i++) c[i][0]=1;    for (int i=1;i<=t;i++)     for (int j=1;j<=i;j++) c[i][j]=(c[i-1][j-1]+c[i-1][j])%p;    f[0][m][0]=1;    for (int i=0;i<=n;i++)      for (int j=0;j<=m;j++)      for (int k=0;k<=m;k++){        if (j+k>m) break;        (f[i+1][j][k]+=f[i][j][k])%=p;        if (j-2>=0)(f[i+1][j-2][k+2]+=(LL)f[i][j][k]*c[j][2]%p)%=p;        if (k-2>=0)(f[i+1][j][k-2]+=(LL)f[i][j][k]*c[k][2]%p)%=p;        if (j-1>=0)(f[i+1][j-1][k]+=(LL)f[i][j][k]*c[k][1]%p*c[j][1]%p)%=p;        if (j-1>=0)(f[i+1][j-1][k+1]+=(LL)f[i][j][k]*c[j][1]%p)%=p;        if (k-1>=0)(f[i+1][j][k-1]+=(LL)f[i][j][k]*c[k][1]%p)%=p;      }    int ans=0;    for (int i=0;i<=m;i++)     for (int j=0;j<=m;j++) ans=(ans+f[n][i][j])%p;    printf("%d\n",ans);}
原创粉丝点击