BZOJ2729:[HNOI2012]排队(组合数学)_组合数学

Description

某中学有 n 名男同学,m 名女同学和两名老师要排队参加体检。他们排成一条直线,并且任意两名女同学不能相邻,两名老师也不能相邻,那么一共有多少种排法呢?(注意:任意两个人都是不同的)
 

Input

只有一行且为用空格隔开的两个非负整数 n m,其含义如上所述。
 
对于 30%的数据 n≤100,m≤100
 
对于 100%的数据 n≤2000,m≤2000

Output

输出文件 output.txt 仅包含一个非负整数,表示不同的排法个数。注意答案可能很大。

Sample Input

1 1

Sample Output

12

Solution

一种情况是两个老师中间只有一个人且这个人是女生。

即$A(n,n)*A(n+1,1)*A(2,2)*A(m,1)*A(n+2,m-1)$

另一种情况是两个老师中间不是只有一个女生,也就是两个老师中间一定有男生。

即$A(n,n)*A(n+1,2)*A(n+3,m)$

Code

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<cmath>
  5 #include<algorithm>
  6 #define MAX_L 20005
  7 using namespace std;
  8 
  9 class bign
 10 {
 11     public:
 12         int len, s[MAX_L];
 13         bign();
 14         bign(const char*);
 15         bign(int);
 16         bool sign;
 17         string toStr() const;
 18         friend istream& operator>>(istream &,bign &);
 19         friend ostream& operator<<(ostream &,bign &);
 20         bign operator=(const char*);
 21         bign operator=(int);
 22         bign operator=(const string);
 23         bool operator>(const bign &) const;
 24         bool operator>=(const bign &) const;
 25         bool operator<(const bign &) const;
 26         bool operator<=(const bign &) const;
 27         bool operator==(const bign &) const;
 28         bool operator!=(const bign &) const;
 29         bign operator+(const bign &) const;
 30         bign operator++();
 31         bign operator++(int);
 32         bign operator+=(const bign&);
 33         bign operator-(const bign &) const;
 34         bign operator--();
 35         bign operator--(int);
 36         bign operator-=(const bign&);
 37         bign operator*(const bign &)const;
 38         bign operator*(const int num)const;
 39         bign operator*=(const bign&);
 40         bign operator/(const bign&)const;
 41         bign operator/=(const bign&);
 42         bign operator%(const bign&)const;
 43         bign factorial()const;
 44         bign Sqrt()const;
 45         bign pow(const bign&)const;
 46         void clean();
 47         ~bign();
 48 };
 49 
 50 bign::bign()
 51 {
 52     memset(s,0,sizeof(s));
 53     len=1;
 54     sign=1;
 55 }
 56 
 57 bign::bign(const char *num)
 58 {
 59     *this=num;
 60 }
 61 
 62 bign::bign(int num)
 63 {
 64     *this=num;
 65 }
 66 
 67 string bign::toStr() const
 68 {
 69     string res;
 70     res="";
 71     for (int i=0; i<len; i++)
 72         res=(char)(s[i]+'0')+res;
 73     if (res=="")
 74         res="0";
 75     if (!sign&&res!="0")
 76         res="-"+res;
 77     return res;
 78 }
 79 
 80 istream &operator>>(istream &in, bign &num)
 81 {
 82     string str;
 83     in>>str;
 84     num=str;
 85     return in;
 86 }
 87 
 88 ostream &operator<<(ostream &out, bign &num)
 89 {
 90     out<<num.toStr();
 91     return out;
 92 }
 93 
 94 bign bign::operator=(const char *num)
 95 {
 96     memset(s,0,sizeof(s));
 97     char a[MAX_L]="";
 98     if (num[0]!='-')
 99         strcpy(a,num);
100     else
101         for (int i=1,l=strlen(num); i<l; i++)
102             a[i-1]=num[i];
103     sign=!(num[0]=='-');
104     len=strlen(a);
105     for (int i=0; i<strlen(a); i++)
106         s[i]=a[len-i-1]-48;
107     return *this;
108 }
109 
110 bign bign::operator=(int num)
111 {
112     char temp[MAX_L];
113     sprintf(temp,"%d",num);
114     *this=temp;
115     return *this;
116 }
117 
118 bign bign::operator=(const string num)
119 {
120     const char *tmp;
121     tmp=num.c_str();
122     *this=tmp;
123     return *this;
124 }
125 
126 bool bign::operator<(const bign &num) const
127 {
128     if (sign^num.sign)
129         return num.sign;
130     if (len!=num.len)
131         return len<num.len;
132     for (int i=len-1; i>=0; i--)
133         if (s[i]!=num.s[i])
134             return sign?(s[i]<num.s[i]):(!(s[i]<num.s[i]));
135     return !sign;
136 }
137 
138 bool bign::operator>(const bign&num)const
139 {
140     return num<*this;
141 }
142 
143 bool bign::operator<=(const bign&num)const
144 {
145     return !(*this>num);
146 }
147 
148 bool bign::operator>=(const bign&num)const
149 {
150     return !(*this<num);
151 }
152 
153 bool bign::operator!=(const bign&num)const
154 {
155     return *this>num || *this<num;
156 }
157 
158 bool bign::operator==(const bign&num)const
159 {
160     return !(num!=*this);
161 }
162 
163 bign bign::operator+(const bign &num) const
164 {
165     if (sign^num.sign)
166     {
167         bign tmp=sign?num:*this;
168         tmp.sign=1;
169         return sign?*this-tmp:num-tmp;
170     }
171     bign result;
172     result.len=0;
173     int temp=0;
174     for (int i=0; temp || i<(max(len, num.len)); i++)
175     {
176         int t=s[i]+num.s[i]+temp;
177         result.s[result.len++]=t % 10;
178         temp=t/10;
179     }
180     result.sign=sign;
181     return result;
182 }
183 
184 bign bign::operator++()
185 {
186     *this=*this+1;
187     return *this;
188 }
189 
190 bign bign::operator++(int)
191 {
192     bign old=*this;
193     ++(*this);
194     return old;
195 }
196 
197 bign bign::operator+=(const bign &num)
198 {
199     *this=*this+num;
200     return *this;
201 }
202 
203 bign bign::operator-(const bign &num) const
204 {
205     bign b=num,a=*this;
206     if (!num.sign && !sign)
207     {
208         b.sign=1;
209         a.sign=1;
210         return b-a;
211     }
212     if (!b.sign)
213     {
214         b.sign=1;
215         return a+b;
216     }
217     if (!a.sign)
218     {
219         a.sign=1;
220         b=bign(0)-(a+b);
221         return b;
222     }
223     if (a<b)
224     {
225         bign c=(b-a);
226         c.sign=false;
227         return c;
228     }
229     bign result;
230     result.len=0;
231     for (int i=0, g=0; i<a.len; i++)
232     {
233         int x=a.s[i]-g;
234         if (i<b.len) x -= b.s[i];
235         if (x >= 0) g=0;
236         else
237         {
238             g=1;
239             x += 10;
240         }
241         result.s[result.len++]=x;
242     }
243     result.clean();
244     return result;
245 }
246 
247 bign bign::operator * (const bign &num)const
248 {
249     bign result;
250     result.len=len+num.len;
251 
252     for (int i=0; i<len; i++)
253         for (int j=0; j<num.len; j++)
254             result.s[i+j] += s[i] * num.s[j];
255 
256     for (int i=0; i<result.len; i++)
257     {
258         result.s[i+1] += result.s[i]/10;
259         result.s[i] %= 10;
260     }
261     result.clean();
262     result.sign=!(sign^num.sign);
263     return result;
264 }
265 
266 bign bign::operator*(const int num)const
267 {
268     bign x=num;
269     bign z=*this;
270     return x*z;
271 }
272 bign bign::operator*=(const bign&num)
273 {
274     *this=*this * num;
275     return *this;
276 }
277 
278 bign bign::operator /(const bign&num)const
279 {
280     bign ans;
281     ans.len=len-num.len+1;
282     if (ans.len<0)
283     {
284         ans.len=1;
285         return ans;
286     }
287 
288     bign divisor=*this, divid=num;
289     divisor.sign=divid.sign=1;
290     int k=ans.len-1;
291     int j=len-1;
292     while (k >= 0)
293     {
294         while (divisor.s[j]==0) j--;
295         if (k > j) k=j;
296         char z[MAX_L];
297         memset(z, 0, sizeof(z));
298         for (int i=j; i >= k; i--)
299             z[j-i]=divisor.s[i]+'0';
300         bign dividend=z;
301         if (dividend<divid)
302         {
303             k--;
304             continue;
305         }
306         int key=0;
307         while (divid*key <= dividend) key++;
308         key--;
309         ans.s[k]=key;
310         bign temp=divid*key;
311         for (int i=0; i<k; i++)
312             temp=temp * 10;
313         divisor=divisor-temp;
314         k--;
315     }
316     ans.clean();
317     ans.sign=!(sign^num.sign);
318     return ans;
319 }
320 
321 bign bign::operator/=(const bign&num)
322 {
323     *this=*this/num;
324     return *this;
325 }
326 
327 bign bign::operator%(const bign& num)const
328 {
329     bign a=*this, b=num;
330     a.sign=b.sign=1;
331     bign result, temp=a/b*b;
332     result=a-temp;
333     result.sign=sign;
334     return result;
335 }
336 
337 bign bign::pow(const bign& num)const
338 {
339     bign result=1;
340     for (bign i=0; i<num; i++)
341         result=result*(*this);
342     return result;
343 }
344 
345 bign bign::factorial()const
346 {
347     bign result=1;
348     for (bign i=1; i <= *this; i++)
349         result*=i;
350     return result;
351 }
352 
353 void bign::clean()
354 {
355     if (len==0) len++;
356     while (len>1 && s[len-1]=='\0')
357         len--;
358 }
359 
360 bign bign::Sqrt()const
361 {
362     if(*this<0)return -1;
363     if(*this<=1)return *this;
364     bign l=0,r=*this,mid;
365     while(r-l>1)
366     {
367         mid=(l+r)/2;
368         if(mid*mid>*this) r=mid;
369         else l=mid;
370     }
371     return l;
372 }
373 
374 bign::~bign()
375 {
376 }
377 
378 bign A(int n,int m)
379 {
380     bign ans;
381     ans=1;
382     for (int i=n-m+1; i<=n; ++i) ans*=i;
383     return ans;
384 }
385 
386 int n,m; 
387 
388 int main()
389 {
390     scanf("%d%d",&n,&m);
391     bign 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);
392     cout<<ans;
393 }