hdu4248 A Famous Stone Collector

A Famous Stone Collector

Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 19    Accepted Submission(s): 4


Problem Description
Mr. B loves to play with colorful stones. There are n colors of stones in his collection. Two stones with the same color are indistinguishable. Mr. B would like to select some stones and arrange them in line to form a beautiful pattern. After several arrangements he finds it very hard for him to enumerate all the patterns. So he asks you to write a program to count the number of different possible patterns.
Two patterns are considered different, if and only if they have different number of stones or have different colors on at least one position.
 

Input
Each test case starts with a line containing an integer n indicating the kinds of stones Mr. B have. Following this is a line containing n integers - the number of available stones of each color respectively. All the input numbers will be nonnegative and no more than 100.
 

Output
For each test case, display a single line containing the case number and the number of different patterns Mr. B can make with these stones, modulo 1,000,000,007, which is a prime number.
 

Sample Input
   
   
   
   
3 1 1 1 2 1 2
 

Sample Output
   
   
   
   
Case 1: 15 Case 2: 8
Hint
In the first case, suppose the colors of the stones Mr. B has are B, G and M, the different patterns Mr. B can form are: B; G; M; BG; BM; GM; GB; MB; MG; BGM; BMG; GBM; GMB; MBG; MGB.
 

Source
Fudan Local Programming Contest 2012


唉……比赛的时候写了好久。。然后100的组合数好像有算错,比赛后瞎搞了一番结果AC了。

题意是输入每种颜色有多少石头,问总共有多少种排法,石头可以不用上。

用插空法做,假设已经放了t个石头,则有t+1个空位,这时候新来的k一种石头就可以放在这t+1个空位上。

假设F(i,j)表示现在有i个空格,要放j个石头。

那么F(i,j)=sum(F(t,j-t)*C(i,t)),0<=t<=min(i,j),C()表示组合数

枚举t表示想将这j个石头放在t个空位里,因此C(i,t)不难理解,就是在i个空位里选t个放,然后将这t个空位每个空位放一个石头,剩下j-t个石头需要再放到这t个空位里,但是允许这t个空位中有部分空位不放,因此就是F(t,j-t),即在这t个空位中放j-t个石头。

比赛的时候的代码,搓死……

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

#define MOD 1000000007

int a[105];
long long c[10005][105];
long long cc[10005][105];
long long dp[10005];

void C()
{
    int i,j;
    long long t;
    for (i=0;i<=10002;i++)
    {
        if (i==102) t=1;
        if (i>102) t=(t*i)%MOD;
        for (j=0;j<=min(i,102);j++)
        {
            if (i==0 || j==0 || i==j) c[i][j]=1;
            else if (j==102) c[i][j]=t;
            else c[i][j]=(c[i-1][j-1]+c[i-1][j])%MOD;
        }
    }
}


long long Com(int i,int j)
{
    if (i==1 || j==0) return 1;
    if (cc[i][j]!=-1) return cc[i][j];
    long long ans=0;
    for (int t=1;t<=min(i,j);t++)
    {
        ans=(ans+Com(t,j-t)*c[i][t])%MOD;
    }
    cc[i][j]=ans;
    return ans;
}

int main()
{
    int i,j,n,m,k,cnt=1;
    long long ans,tag;
    memset(cc,-1,sizeof(cc));
    C();
    while(scanf("%d",&n)!=EOF)
    {
        memset(dp,0,sizeof(dp));
        dp[0]=1;
        m=0;
        for (i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            for (j=m;j>=0;j--)
            {
                for (k=1;k<=a[i];k++)
                {
                    tag=dp[j]*Com(j+1,k)%MOD;
                    dp[j+k]=(dp[j+k]+tag)%MOD;
                }
            }
            m+=a[i];
        }
        ans=0;
        for (i=1;i<=m;i++)
        {
            ans=(ans+dp[i])%MOD;
        }
        printf("Case %d: %I64d\n",cnt++,ans);
    }
    return 0;
}


你可能感兴趣的:(hdu4248 A Famous Stone Collector)