Codeforces 553A Kyoya and Colored Balls【思维】

本文介绍了一道关于排列组合的问题,即如何计算特定条件下不同颜色球的排列方式数量。通过逆向思维和组合数学方法,文章提供了一种有效求解方案,并附带AC代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A. Kyoya and Colored Balls
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard 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

题目大意:

一个袋子中有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


思路:


1、我们逆序思考这个问题,如果我们现在一共有sum个球,那么我们将最后一种颜色的球放在上边有多少种分配方式呢?

我们需要将一个球放在最后一个位子上,那么其余这个颜色的球就可以随便放在sum-1个位子上,那么对应有C(sum-1,其余这个颜色的球的个数);


2、那么我们每一次都将当前颜色的球选一个放在最后边,那么剩余的位子上就可以放这个颜色其他球了,那么对应我们将每个颜色对应可能方案数累乘即可。


3、求Cnm%mod,我们可以用杨辉三角的方法来求,因为总球的个数不会超过1000个,所以我们直接处理即可,不会超时


Ac代码:

#include<stdio.h>
#include<string.h>
using namespace std;
#define mod 1000000007
#define ll __int64
ll a[1515];
ll C[1515][1515];
void init()
{
    C[0][0]=1;
    for(int i=1;i<=1005;i++)
    {
        C[i][i]=C[i][0]=1;
        for(int j=1;j<=1005;j++)
        {
            C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
        }
    }
}
int main()
{
    init();
    int n;
    while(~scanf("%d",&n))
    {
        int sum=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%I64d",&a[i]);
            sum+=a[i];
        }
        ll output=1;
        for(int i=n;i>=1;i--)
        {
            output*=C[sum-1][a[i]-1];
            output%=mod;
            sum-=a[i];
        }
        printf("%I64d\n",output);
    }
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值