codeforces 554C Kyoya and Colored Balls 推公式

题意:有n种颜色的球,每个球有a[i]个,每种颜色的球都是一样的,然后开始取球,要求编号小的球要比编号大的球先取完,即每种颜色最后取得顺序是递增的,就是要先取完第一种最后一个才能开始取第二种最后一个,前面的怎样都行。

解法:推公式,作为一个acm菜比,一个公式推了一个小时,试了各种方法,最后用的插空法,先拿出每种球各一个放在那,作为最后的顺序,假设剩余的每种球都是不一样的,那么对于第一种剩余的球,只能往1号球前面插空,第一个有一种插法,第二个就有两种插法,对于第二种球,只能插在2号球前面,以此类推。

注意,求模用到了乘法逆元

AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#define mod 1000000007
using namespace std;
long long k,c[1005];
long long cnm(long long x)
{
    long long ans = 1;
    for(int i = 1; i <= x; i++)
        {ans *= i;
        ans%=mod;}
    return ans;
}

long long chengfaniyuan(long long a,long long b,long long c)
{
    long long x1,x2,x3,y1,y2,y3,t1,t2,t3,k,ni;
    if(b > c){x2 = b; b = c; c = x2;}
    x1 = 1,x2 = 0,x3 = c;
    y1 = 0,y2 = 1,y3 = b;
    while(1)
    {
        if(y3 == 0) {ni = 0;break;}
        if(y3 == 1) {ni = y2;break;}
        k = x3/y3;
        t1 = x1-k*y1,t2 = x2-k*y2,t3=x3-k*y3;
        x1 = y1,x2=y2,x3=y3;
        y1=t1,y2=t2,y3=t3;
    }
    if(ni < 0) ni+=mod;
    return a*ni%c;
}
int main(){
    long long tot = 1;
    scanf("%lld",&k);
    for(int i = 0; i < k; i++)
        {scanf("%lld",&c[i]);
        c[i] --;}
    long long tem = 0;
    for(int i = 0; i < k; i++)
    {
        tem++;
        for(int j = 0; j < c[i]; j++)
            {tot *= tem++;
            tot%=mod;}
    }
    long long div = 1;
    for(int i = 0; i < k; i++)
        {div*=cnm(c[i]);
        div%=mod;}
    printf("%lld\n",chengfaniyuan(tot,div,mod));
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值