标签:acm
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5155
1 1 2 2 2 3
1 7 25
官方的解答:
dp题,我们一行一行的考虑。dp[i][j],表示前i行,都满足了每一行至少有一个宝石的条件,而只有j列满足了有宝石的条件的情况有多少种。枚举第i+1行放的宝石数k,这k个当中有t个是放在没有宝石的列上的,那么我们可以得到转移方程: dp[i+1][j+t]+=dp[i][j]*c[m-j][t]*c[j][k-t],其中c[x][y],意为在x个不同元素中无序地选出y个元素的所有组合的个数。
代码如下:/* 最好用 long long */ #include <iostream> #include <stdio.h> #include <string> #include <string.h> #include <algorithm> const int mod=1000000007; using namespace std; typedef long long ll; int n,m; ll C[110][110]; ll dp[110][110]; void init()//预处理组合数 { memset(C,0,sizeof(C)); C[0][0]=1; for(int i=1;i<=55;i++) { C[i][0]=1; for(int j=1;j<i;j++) { C[i][j]=C[i-1][j-1]+C[i-1][j]; if(C[i][j]>=mod)C[i][j]%=mod; } C[i][i]=1; } } void DP() { for(int i=1;i<=m;i++)dp[1][i]=C[m][i]; for(int i=2;i<=n;i++) for(int k=1;k<=m;k++) for(int z=0;z<=k;z++) for(int j=1;j<=m;j++) { if( j+z>m || (k-z>j) )continue; ll t=((dp[i-1][j]%mod*C[j][k-z]%mod)%mod*C[m-j][z]%mod)%mod; dp[i][j+z]+=t; dp[i][j+z]%=mod; } printf("%I64d\n",dp[n][m]); } int main() { init(); while(scanf("%d%d",&n,&m)!=EOF) { memset(dp,0,sizeof(dp)); DP(); } return 0; }
标签:acm
原文地址:http://blog.csdn.net/liusuangeng/article/details/42466665