[HNOI2012]排队

组合式能想出来。
首先就是假设两个老师中间只有一个女生,那么把这三个人看成一个整体,还有一种就是两个老师之间不是仅有一个女生,那么有n+3个空隙,女生插空即可。

高精坑死了,char开的10000还不行,开的100000

// luogu-judger-enable-o2
//Writer:jr HSZ;%%%WJMZBMR
#include<bits/stdc++.h>
#define LL long long
#define reg register int
#define f(i,a,b) for(reg i=a;i<=b;i++)
using namespace std;
struct NUM {
    int len;
    int s[100011];
    NUM() {
        memset(s,0,sizeof s);
    }
    NUM(int num) {
        *this = num;
    }
    NUM(const char* num) {
        *this = num;
    }
    NUM operator = (int num) {
        char s[100011];
        sprintf(s,"%d",num);
        *this = s;
        return *this;
    }
    string str()const {
        string res = "";
        for(int i=0; i<len; i++) {
            res=(char)(s[i]+'0')+res;
        }
        if(res=="")res="0";
        return res;
    }
    void clean(){
        while(len>1&&!s[len-1])len--;
    }
    NUM operator  = (const char *num) {
        len=strlen(num);
        f(i,0,len-1)s[i]=num[len-i-1]-'0';
        return *this;
    }
    NUM operator + (const NUM& b) const {
        NUM c;
        c.len=0;
        for(int i=0,g=0; i<max(len,b.len)||g; i++) {
            int x=g;
            if(i<len)x+=s[i];
            if(i<b.len)x+=b.s[i];
            c.s[c.len++]=x%10;
            g=x/10;
        }
        return c;
    }
    NUM operator * (const NUM& b) {
        NUM c;
        c.len=len+b.len;
        f(i,0,len-1){
            f(j,0,b.len-1){
                c.s[i+j]+=s[i]*b.s[j];
            }
        }
        f(i,0,c.len-2)
        {
            c.s[i+1]+=c.s[i]/10;
            c.s[i]%=10;
        }
        c.clean();
        return c;
    }
    NUM operator - (const NUM& b) { 
    NUM c; c.len = 0; 
    for(int i = 0, g = 0; i < len; i++) { 
      int x = s[i] - g; 
      if(i < b.len) x -= b.s[i]; 
      if(x >= 0) g = 0; 
      else { 
        g = 1; 
        x += 10; 
      } 
      c.s[c.len++] = x; 
    } 
    c.clean(); 
    return c; 
  } 
  bool operator < (const NUM& b) const{ 
    if(len != b.len) return len < b.len; 
    for(int i = len-1; i >= 0; i--) 
      if(s[i] != b.s[i]) return s[i] < b.s[i]; 
    return false; 
  } 
  bool operator > (const NUM& b) const{ 
    return b < *this; 
  } 
  bool operator <= (const NUM& b) { 
    return !(b > *this); 
  } 
  bool operator == (const NUM& b) { 
    return !(b < *this) && !(*this < b); 
  } 
  NUM operator += (const NUM& b) { 
    *this = *this + b; 
    return *this; 
  } 
};
istream& operator >> (istream &in, NUM& x) { 
  string s; 
  in >> s; 
  x = s.c_str(); 
  return in; 
} 
ostream& operator << (ostream &out, const NUM& x) { 
  out << x.str(); 
  return out; 
} 
NUM A(int x,int y) {
    NUM ans=1;
    if(x<y)return ans=0;
    if(!y) return ans=1;
    ans=1;
    for(long long i=x-y+1;i<=x;i++) ans=ans*i;
    return ans;
} 
int n,m;
int main() {
    scanf("%d%d",&n,&m);
    NUM ans=A(n,n)*A(n+1,2)*A(n+3,m)/*两个老师中间不止一个女生*/+A(n,n)*A(n+1,1)*A(2,2)*A(m,1)*A(n+2,m-1)/*两个老师中间隔一个女生*/;
    cout<<ans;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/sdfzhsz/p/9292031.html