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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章