排队(排列组合)

归档于 2019-06-27 11:15

题目大意:

两个老师,n个男,m个女,女不互邻,老师不互邻 方案

不是${A_n^n}{A_{n+1}^m}{A_{n+m+1}^2}$,也不是${A_n^n}{A_{n+1}^2}{A_{n+3}^m}$

因为这两种都没有考虑两个老师||两个女生互邻然后中间再插一个(挡板法默认不相邻)

首先用${A_{n+1}^{n+1}}$$*$ ${A_{n+2}^{m-1}}$$m2$求出老师老师之间插男生时情况

那么应该再加上两个老师之间插一个女生

首先默认两个老师相邻因为两个老师不同,所以有两种情况${A_2^2}$,然后中间塞一个女生有m种情况;

然后把“”老师“”–“”女生“”–“”老师“”看作一个组合体即看成一个男生

然后剩余m-1个女生往n+2个空里插

所得${A_{n+1}^{n+1}}$$*$$A_{n+2}^{m-1}$$m2$``

最终相加得到$ans=$${A_n^n}{A_{n+1}^2}{A_{n+3}^m}$$+$${A_{n+1}^{n+1}}$$*$$A_{n+2}^{m-1}$$m2$

以下是本人丑陋的代码

#include<bits/stdc++.h>
#define ll long long
#define N 10000
#define P 4
using namespace std;
ll n,m;
struct bignum
{
    ll n[20000],l;
    bignum(){l=1,memset(n,0,sizeof(n));}
    void clear(){while(l>1&&!n[l-1]) l--;}
    void print()
    {
        printf("%lld",n[l-1]);
        for(ll i=l-2;i>=0;i--)
        printf("%0*lld",P,n[i]);
        printf("\n");
    }
    bignum operator = (ll x)
    {
        l=0;    
        while(x)
        {
            n[l++]=x%N;
            x/=N;
        }
        return *this;
    }
    bignum operator +(bignum x) const
    {
        bignum t=*this;
        if(x.l>t.l) t.l=x.l;        
        for(ll i=0;i<t.l;i++)
        {
            t.n[i]+=x.n[i];
            if(t.n[i]>=N)
            {
                t.n[i+1]+=t.n[i]/N;
                t.n[i]%=N;
            }
        }
        return t;
    }
       bignum operator * (const ll& b)
      {
        bignum c;
           c.l=0;
        for(ll i=0,g=0;g||i<l;i++)
        {
            ll x;
            if(i<l)x=n[i]*b+g;
            else x=g;
            c.n[c.l++]=x%N;
            g=x/N;
        }
        return c;
    }
    bignum operator *(bignum x) const
    {
        bignum t=*this,tep;
        tep.l=t.l+x.l;
        for(ll i=0;i<t.l;i++)
            for(ll j=0;j<=x.l;j++)
            {
                tep.n[i+j]+=t.n[i]*x.n[j];
            }
        for(ll i=0;i<tep.l;i++)
        {
            tep.n[i+1]+=tep.n[i]/N;
            tep.n[i]%=N;
        }
        tep.clear();
        return tep;
    }    

    bool operator <(bignum x) const
    {
        bignum t=*this,tep;
        if(t.l!=x.l)    return t.l<x.l;
        for(ll i=t.l-1;i>=0;i--)
        {
            if(t.n[i]!=x.n[i]) return t.n[i]<x.n[i];
        }
        return 0;
    }
    bool operator >(bignum x) const
    {
        bignum t=*this;
        if(t.l!=x.l) return t.l>x.l;
        for(ll i=t.l-1;i>=0;i--)
        {
            if(t.n[i]!=x.n[i]) return t.n[i]>x.n[i];
        }
        return 0;
    }
    bignum operator -(bignum x) const
    {
        bignum t=*this;
        if(t<x) printf("-");swap(t,x);
        ll jie=0;
        for(ll i=0;i<t.l;i++)
        {
            t.n[i]-=x.n[i];
            while(t.n[i]<0)
            {
                t.n[i]+=N;
                jie++;
            }
            t.n[i+1]-=jie;
            jie=0;
        }
        while(!t.n[t.l-1]&&t.l>1) t.l--;
        return t;
    }

}ans,c;
bignum A(ll m,ll n)
{
//    if(m>n) return bignum();
    bignum c;
    c=1;
    for(ll i=n-m+1;i<=n;i++)
        c=c*i;
    return c;
}
int main()
{
    cin>>n>>m;
    ans=0;
    ans=A(n,n)*(A(2,n+1)*A(m,n+3)+A(1,n+1)*A(2,2)*A(1,m)*A(m-1,n+2));
    ans.print();
}

View Code