codeforces 554C Kyoya and Colored Balls 推公式

来源:互联网 发布:艺术签名免费设计软件 编辑:程序博客网 时间:2024/06/05 14:12

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

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

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

AC代码:

#include <cstdio>#include <cstring>#include <algorithm>#define mod 1000000007using 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