一个袋子中有n个彩球,他们用k种不同的颜色染色。颜色被从1到k编号。同一种颜色的球看成是一样的。现在从袋中一个一个的拿出球来,直到拿完所有的球。对于所有颜色为i (1<=i<=k-1)的球,他的最后一个球总是在编号比他大的球拿完之前拿完,问这样情况有多少种。
样例解释:这个样例中有2个1号颜色的球,2个2号颜色的球,1个3号颜色的球。三种方案是:
1 2 1 2 3
1 1 2 2 3
2 1 1 2 3
Input
单组测试数据。 第一行给出一个整数k(1 ≤ k ≤ 1000),表示球的种类。 接下来k行,每行一个整数ci,表示第i种颜色的球有ci个(1 ≤ ci ≤ 1000)。 球的总数目不超过1000。
Output
输出总数对1,000,000,007的模即可。
Input示例
3 2 2 1
Output示例
3
突然觉得算法不需要会那么多 ,关键是怎么用。。读了一整天 。看了好多题解 ,,才算理解这个题的做法。
倒着看 ,最后一个颜色的球肯定放在最后一个位置 ,,然后剩下的位置排列组合,,之后 ,连乘下去。最后就是要得到的结果。
就是组合数连乘= = 。。突然就变成水题了。。构思很重要,思维很重要 。
倒着想 一共需要s个位置 。然后最后一种颜色有sum个
那么 放一个到末尾 然后 剩下s-1 个位置放sum个球 。。。
之后 位置剩下s-sum个 倒数第二种颜色的球有 sum1个
然后 就是 s-sum-1 个位置放下sum1个球 。
是不是水了许多???
#include <bits/stdc++.h>
using namespace std;
#define mo 1005
long long s[mo][mo];
const long long mod=1e9+7;
int main()
{
s[0][0]=1;
for(long long i=1;i<mo;i++)
{
s[i][0]=1;
for(long long j=1;j<mo;j++)
{
s[i][j]=(s[i-1][j]+s[i-1][j-1])%mod;
}
}
long long n;
while(cin>>n)
{
long long ans=1;
long long q=0;
long long x;
for(long long i=1;i<=n;i++)
{
cin>>x;
q+=x;
if(i>1)ans=(ans*s[q-1][x-1])%mod;
//cout<<ans<<' '<<s[q][x-1]<<' '<<q<<endl;
}
cout<<ans<<endl;
}
}