Famous Stone Collector HDU

来源:互联网 发布:软件手术刀怎么用 编辑:程序博客网 时间:2024/06/05 17:56

题意:给你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  1000000007void 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;}
原创粉丝点击