Kyoya and Colored Balls(组合数学)

Kyoya Ootori has a bag with n colored balls that are colored with k different colors. The colors are labeled from 1 to k. Balls of the same color are indistinguishable. He draws balls from the bag one by one until the bag is empty. He noticed that he drew the last ball of color i before drawing the last ball of color i + 1 for all i from 1 to k - 1. Now he wonders how many different ways this can happen.

Input
The first line of input will have one integer k (1 ≤ k ≤ 1000) the number of colors.

Then, k lines will follow. The i-th line will contain ci, the number of balls of the i-th color (1 ≤ ci ≤ 1000).

The total number of balls doesn’t exceed 1000.

Output
A single integer, the number of ways that Kyoya can draw the balls from the bag as described in the statement, modulo 1 000 000 007.

Examples
Input
3
2
2
1
Output
3
Input
4
1
2
3
4
Output
1680
Note
In the first sample, we have 2 balls of color 1, 2 balls of color 2, and 1 ball of color 3. The three ways for Kyoya are:

1 2 1 2 3
1 1 2 2 3
2 1 1 2 3
题目分析:
做这个题时一打眼便想到了高中的排列组合,但从来没有接触过组合数学的东西,尤其是在程序实现这方面,所以一开始在傻傻的弄阶乘,后来搜了一下组合数学的知识,发现了杨辉三角的方法,不是一般的方便。
CnmC^{m} _ {n}=Cn1m1C^{m-1}_{n-1}+Cn1mC^{m}_{n-1}
这就是杨辉三角法,一般用来预处理打表,时间复杂度O(n2n^{2}
预备知识讲完就可以接触这个题了,这个题既然是让每种颜色的最后一个球的下一个球必须是下一个颜色的,那么我们就可以从最后一个球开始放,假设k颜色的球有m个,把k颜色的最后一个球放在最后一位上,这时k颜色的球只剩下了m-1个,(假设总球数为sum)那么这时候还有sum-1个空位可以放,运用组合数可以把m-1个球放在sum-1个位置上的所有情况表达出来,就是Csum1m1C^{m-1}_{sum-1}意思是什么呢,就是把m-1个球随机放在sum-1个位置中随机的m-1个位置上。那么接下来就要处理下一个位置上的球啦。
首先我们先来整理一下现有的数据,还有sum-m个球,假设k-1颜色球有p个。
那么我们把k-1颜色的球的最后一个球放在当前情况的最后一位上,然后接下来的处理方式就和上一个球一样了呀,给剩下的p-1个球找存放位置,结果是Csumm1p1C^{p-1}_{sum-m-1}
然后我们就可以计算这些结果的乘积了,注意是相乘而不是相加,他们不是独立的情况,而是相互有影响的。别忘记取模和处理只有一个球的情况这道题就做完了。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<string>
using namespace std;
const int mod=1e9+7;
long long c[1001][1001];
int num[1001];
void chu()
{
    for(int i=1;i<=1000;i++)
    {
        c[i][0]=1;
        c[i][i]=1;
        for(int j=1;j<i;j++)
        {
            c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;//杨辉三角预处理出所有组合数
        }
    }
}
int main()
{
    chu();
    int k;
    long long ans=1,sum=0;
    cin>>k;
    for(int i=1;i<=k;i++)
    {
        cin>>num[i];
        sum+=num[i];
    }
    for(int i=k;i>=1;i--)
    {
        if(num[i]==1)
        {
            sum--;
            continue;
        }
        ans=(ans*c[sum-1][num[i]-1])%mod;
        sum-=num[i];
    }
    cout<<ans<<endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章