【原创】【组合数学】HDU 4248 A Famous Stone Collector

来源:互联网 发布:中国古代名言警句软件 编辑:程序博客网 时间:2024/05/16 10:19

A Famous Stone Collector

题目

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.

翻译

Mr.B有n种颜色的石头,每种颜色的石头有A[i]个,用石头摆图案,求图案的方案数。
其实就相当于有n种颜色的小球,每种颜色有一定的数量,小球除了颜色没有区别,求方案数。

分析

状态转移方程式:
dp[i][j]//表示用到第i种颜色,用了j块石头
=dp[i-1][j-k]*C[j][k](0<=k<=min(A[i],j))

我们枚举k,表示我们放了k个i颜色石头,
所以说,前面i-1个颜色就占了j-k个位置,而这么放的方案数已知,因此要加上dp[i-1][j-k],
还有k个位置,这k个位置有多少种情况呢?就是C(n,k)//C是组合

预处理组合数就行了,最后注意精度、取模以及多组数据。

代码

#include<cstdio>#include<algorithm>#include<iostream>#include<cstring>using namespace std;#define ll long long#define mod 1000000007ll C[10005][105],dp[105][10005];void Sc(){    C[0][0]=1LL;    for(int i=1;i<=10000;i++)    {        C[i][0]=1LL;        for(int j=1;j<=100&&j<=i;j++)            C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;    }}int n,A[105];int main(){    Sc();    int cr=0;    while(scanf("%d",&n)!=EOF)    {        for(int i=1;i<=n;i++) scanf("%d",&A[i]);        ll sig=0LL;        memset(dp,0,sizeof dp);        dp[0][0]=1;        for(int i=1;i<=n;i++)        {            sig+=A[i];            for(ll j=0;j<=sig;j++)                for(ll k=0;k<=A[i]&&k<=j;k++)                    dp[i][j]=(dp[i][j]+dp[i-1][j-k]%mod*C[j][k]%mod)%mod;        }        ll ans=0LL;        for(ll i=1;i<=sig;i++)            ans+=dp[n][i],ans%=mod;        printf("Case %d: ",++cr);        cout<<ans<<endl;    }}
原创粉丝点击