【47.95%】【codeforces 554C】Kyoya and Colored Balls

time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
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

【题目链接】:http://codeforces.com/contest/554/problem/C

【题解】

题意:
设第i种颜色的球出现的最后一个位置为x
第i+1种颜色的球出现的最后一个位置为y;
则严格要求x< y;
问这样的序列有多少个.
解法:
先设所有的颜色的球总共有n个;即n=c1+c2..ck;
可以从最后一种颜色即颜色为k的球开始考虑;
现在有n个位置让你摆这第k种颜色的球;
先考虑第k种颜色的最后一个球要放在哪里?
肯定是第n个位置.
因为如果不放在第n个位置,则可能会有其他的球在后面的过程中放在第n个位置,而不管这个球的颜色是什么,它的颜色编号都比k小;这就不满足上上述要求了,因为那种颜色的球最后一次出现的位置肯定比k大..
因此把第k种颜色的球的最后一个放在第n个位置;
接下来第k种颜色的球还有ck-1个;剩下的位置还有n-1个;
显然剩下的ck-1个球放在哪里都行即C(n-1,ck-1);
放完第k个球再考虑第k-1种颜色的球.
还是一样先考虑第k-1种颜色的球的最后出现的球应该放在哪里??
肯定是第k中颜色的球放剩下的位置里面的最后一个位置.道理还是一样,如果不先占据那个位置则其他编号比k-1小的球可以放在那里(设为位置x),则编号为k-1的球的最后一次出现的位置肯定小于x,而位置为x的球的编号小于k-1????显然就不合适了。。
所以先把编号为k-1的球中的一个拿出来放在位置x(即第k中颜色的球放剩下的位置里面的最后一个位置);
然后剩下n-c[k]-c[k-1]-1个位置,从中选出c[k-1]-1位置放剩下的c[k-1]-1个球….
即C(n-c[k]-c[k-1]-1,c[k-1]-1);
以此类推..

【完整代码】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rei(x) scanf("%d",&x)
#define rel(x) scanf("%I64d",&x)

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

const int MAXN = 1e3+10;
const int MOD = 1e9+7;
const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);

int k,n = 0;
int c[MAXN][MAXN];

int main()
{
    //freopen("F:\rush.txt","r",stdin);
    c[0][0] = 1;
    rep1(i,1,1000)
        c[i][i] = 1,c[i][0] = 1;
    rep1(i,1,1000)
        rep1(j,1,1000)
            {
                c[i][j] =c[i-1][j]+c[i-1][j-1];
                if (c[i][j] >= MOD) c[i][j]-=MOD;
            }
    LL ans = 1;
    rei(k);
    rep1(i,1,k)
    {
        int x;
        rei(x);
        n+=x;
        ans = (ans*c[n-1][x-1])%MOD;
    }
    cout << ans << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/AWCXV/p/7626833.html