您的位置:首页 > 其它

Famous Stone Collector HDU - 4248 组合数学+dp

2017-07-07 11:37 447 查看
题意:给你n种物品的数量,相同物品不能区分,不同物品可以区分,问你排列的总数量。

之前做过dp的计数问题,是计算组合的总数量。排列的总数量就是状态方程改了一下。

dp[i][j]=(dp[i][j]+dp[i-1][j-k]*c[j][k]%inf)%inf;//c[i][j]:在j个位置上取k个的方案数。

因为数组大小,WA了几发。。为什么不出RE。。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
const int maxn = 105;
int a[maxn];
long long dp[maxn][maxn*maxn];
long long c[maxn*maxn][maxn];
#define inf  1000000007

void init()
{
c[1][0]=c[1][1]=c[0][0]=1;
for(int i=2;i<=10010;i++)
{
c[i][0]=c[i][i]=1;
for(int j=1;j<=100;j++)
c[i][j]=(c[i-1][j]+c[i-1][j-1])%inf;
}
return ;
}

void Read(int &x)
{
x=0;char c=getchar();
bool flag=0;
while(c<'0'||'9'<c){
if(c=='-') flag=1;
c=getchar();
}
while('0'<=c&&c<='9') {
x=x*10+c-'0';c=getchar();
}
if(flag) x=-x;
}
int main()
{
int n;
init();
int case1=0;
while(~scanf("%d",&n))
{
int sum=0;
for(int i=0;i<n;i++){
Read(a[i]);
sum+=a[i];
}
memset(dp,0,sizeof(dp));
for(int i=0;i<=a[0];i++) dp[0][i]=1;
for(int i=1;i<n;i++)
{
for(int j=0;j<=sum;j++)
{
int lim=min(j,a[i]);
for(int k=0;k<=lim;k++)
{
dp[i][j]=(dp[i][j]+dp[i-1][j-k]*c[j][k]%inf)%inf;
}
}
}
long long ans=0;
printf("Case %d: ",++case1);
for(int i=1;i<=sum;i++)
ans=(ans+dp[n-1][i])%inf;
printf("%I64d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: