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 }