[BZOJ 2729][HNOI2012]排队:高精度+组合数

来源:互联网 发布:导航网站用什么域名好 编辑:程序博客网 时间:2024/05/14 19:47

点击这里查看原题

组合数问题,需要用到高精度。
把男生和老师混在一起,中间插入女生。两个老师刚好连在一起的情况为
A ( n+1 , n+1 ) * A ( 2 , 2 )
这种情况下两个老师间必须插入女生,于是将两个老师和一个女生捆绑在一起,情况为
m * A ( n+1 , n+1 ) * A ( 2 , 2 )
然后将剩余女生插入,情况为
A ( n+2 , m-1 )

两个老师不连在一起的情况为
A ( n+2 , n+2 ) - A ( n+1 , n+1 ) * A ( 2 , 2 )
直接插入女生的情况为
A ( n+3 , m )

于是,最终答案为
m * A ( n+1 , n+1 ) * A ( 2 , 2 ) * A ( n+2 , m-1 ) + A ( n+2 , n+2 ) - A ( n+1 , n+1 ) * A ( 2 , 2 ) * A ( n+3 , m )

高精度数组不能开太大,我最初开了5e4一直TLE。

/*User:SmallLanguage:C++Problem No.:2729*/#include<bits/stdc++.h>#define ll long long#define inf 999999999using namespace std;int n,m;struct bignum{    int len,c[10005];    bignum(){        len=0;        memset(c,0,sizeof(c));    }}x,y,z;bignum operator+(const bignum a,const bignum b){    bignum c;    c.len=max(a.len,b.len);    for(int i=1;i<=c.len;i++){        c.c[i]+=b.c[i]+a.c[i];        if(c.c[i]>=10000){            c.c[i+1]++;            c.c[i]-=10000;        }    }    if(c.c[c.len+1]) c.len++;    return c;}bignum operator-(const bignum a,const bignum b){    bignum c;    c.len=a.len;    for(int i=1;i<=c.len;i++){        c.c[i]+=a.c[i]-b.c[i];        if(c.c[i]<0){            c.c[i+1]--;            c.c[i]+=10000;        }    }    while(c.c[c.len]==0) c.len--;    return c;}bignum mul(bignum a,int b){    bignum c;    if(b==0){        for(int i=1;i<=c.len;i++) c.c[i]=0;        c.len=1;        return c;    }    c.len=a.len;    for(int i=1;i<=c.len;i++){        c.c[i]+=b*a.c[i];        c.c[i+1]+=c.c[i]/10000;        c.c[i]%=10000;    }    while(c.c[c.len+1]) c.len++;    return c;}void write(bignum p){    printf("%d",p.c[p.len]);    for(int i=p.len-1;i;i--) printf("%04d",p.c[i]);    printf("\n");}int main(){    freopen("data.in","r",stdin);//    scanf("%d%d",&n,&m);    if(n+m==0||m>n+3){        printf("0\n");        return 0;    }    x.len=1;    x.c[1]=1;    y=z=x;    x=mul(x,m);    for(int i=2;i<=n+1;i++) x=mul(x,i);    x=mul(x,2);    for(int i=n+4-m;i<=n+2;i++) x=mul(x,i);    for(int i=2;i<=n+2;i++) y=mul(y,i);    for(int i=2;i<=n+1;i++) z=mul(z,i);    z=mul(z,2);    y=y-z;    for(int i=n+4-m;i<=n+3;i++) y=mul(y,i);    x=x+y;    write(x);    return 0;}
0 0
原创粉丝点击