BZOJ 2729 [HNOI2012]排队

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2729

题目大意: n 名男同学,名女同学和两名老师排队,并且任意两名女同学不能相邻,两名老师也不能相邻,求方案数。

分析:赤果果的排列组合嘛,不会就去问数学老师吧。

盗图一张:

不过还要加高精度。有一个小优化就是把因子存在一个数组里,能约掉的约掉后再高精度乘起来。但是数据很小所以没太大的必要,所以直接高精了。

 

附代码:

View Code
#include<cstdio>

#include<cstdlib>

#include<cstring>

#include<iostream>

using namespace std;

#define MaxL 2000

const long long MOD=1000000000;

struct Bignum

{

    int len;

    long long a[MaxL];

    void init()

    {



        }

    Bignum()

    {

        len=0;

        memset(a,0,sizeof(a));

        }

};



int n,m;

Bignum ans1,ans2;



void operator *= (Bignum &p,int x)

{

    int tmp=0;

    for (int i=1;i<=p.len;++i)

    {

        p.a[i]=p.a[i]*x+tmp;

        tmp=p.a[i]/MOD;

        p.a[i]%=MOD;

        }

    if (tmp)

    p.a[++p.len]=tmp;

    }



Bignum operator + (Bignum x,Bignum y)

{

    int len=max(x.len,y.len);

    int tmp=0;

    for (int i=1;i<=len;++i)

    {

        x.a[i]=x.a[i]+y.a[i]+tmp;

        tmp=x.a[i]/MOD;

        x.a[i]%=MOD;

        }

    x.len=len;

    if (tmp)

        x.a[++x.len]=tmp;

    return x;

    }



Bignum operator * (Bignum x,Bignum y)

{

    Bignum p;

    p.len=0;

    for (int i=1;i<MaxL;++i)

        p.a[i]=0;

    for (int i=1;i<=x.len;++i)

    {

        int tmp=0;

        for (int j=1;j<=y.len;++j)

        {

            p.a[i+j-1]=p.a[i+j-1]+x.a[i]*y.a[j]+tmp;

            tmp=p.a[i+j-1]/MOD;

            p.a[i+j-1]%=MOD;    

            }

        if (tmp)

        p.a[i+y.len]+=tmp;

    }

    int tmp=0;

    for (int i=1;i<MaxL;++i)

    {

        p.a[i]=p.a[i]+tmp;

        tmp=p.a[i]/MOD;

        p.a[i]%=MOD;

        }

    for (int i=MaxL-1;i>=1;--i)

    if (p.a[i])

    {

        p.len=i;

        break;

        }

    if (!p.len) p.len=1;

    return p;

    }



void write(Bignum p)

{

    

    printf("%lld",p.a[p.len]);

    for (int i=p.len-1;i>=1;--i)

    printf("%09lld",p.a[i]);

    printf("\n");

    }



Bignum A(int n,int m)

{

    Bignum p;

    p.len=1;

    p.a[1]=1;

    for (int i=0;i<m;++i)

        p*=(n-i);

    return p;

    }



int main()

{

    scanf("%d%d",&n,&m);

    if (n>=1 && n+3>=m)

    {

        ans1=A(n+3,m);

        ans1*=((n+1)*n);

        }

    if (m>=1 && n+3>=m)

    {

        ans2=A(n+2,m-1);

        ans2*=(2*(n+1)*m);

        }

    write(A(n,n)*(ans1+ans2));

    return 0;

    }

 

 

写这个题是现学的高精乘高精啊...

你可能感兴趣的:(2012)