1. 程式人生 > >HNOI 2012/codevs 1994:排隊

HNOI 2012/codevs 1994:排隊

mod n+2 play 含義 col push_back gif sample efi

技術分享
題目描述 Description
某中學有n 名男同學,m 名女同學和兩名老師要排隊參加體檢。他們排成一條直線,並且任意兩名女同學不能相鄰,兩名老師也不能相鄰,那麽一共有多少種排法呢?(註意:任意兩個人都是不同的)

輸入描述 Input Description
輸入文件只有一行且為用空格隔開的兩個非負整數n 和m,其含義如上所述。

輸出描述 Output Description
僅包含一個非負整數,表示不同的排法個數。註意答案可能很大。

樣例輸入 Sample Input
樣例輸入1
1 1

樣例輸入2
7 3

樣例輸出 Sample Output

樣例輸出1
12


樣例輸出2
220631040 數據範圍及提示 Data Size & Hint 對於30%的數據n≤100,m≤100 對於100%的數據n≤2000,m≤2000
題目

這裏插空法+高精度重載我的公式就是ans=A(n,n)*A(n+1,2)*A(n+3,m)+A(n,n)*C(m,1)*A(2,2)*C(n+1,1)*A(n+2,m-1)

先讓n個男生站好,讓兩個老師插n+1個空,再讓女生插n+3個空,但是忽略了老師和女生站在一起的情況——兩個老師中間夾著一個女生。再讓n個男生站好,在女生裏選出一個來站在老師中間,老師的位置可以互換。這三個人可以在n+1個空裏選一個去站。現在還剩m-1個女生,n+2個空,再讓她們去隨便站就好啦。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<iostream>
  5 #include<cmath>
  6 #include<vector>
  7 #define mod 100000000
  8 #define ll long long
  9 using namespace std;
 10 struct NUM
 11 {
 12     vector<ll>val;    
 13     NUM(){val.clear();val.resize(1
,0);} 14 void clear(){while(!val.back()&&val.size()>1) val.pop_back();} 15 NUM operator+(NUM b) 16 { 17 NUM a=*this,c; 18 int len1=a.val.size(); 19 int len2=b.val.size(); 20 int len3=max(len1,len2)+1; 21 c.val.resize(len3,0); 22 for(int i=0;i<len3;++i){ 23 if(i<len1) c.val[i]+=a.val[i]; 24 if(i<len2) c.val[i]+=b.val[i]; 25 if(i<len3-1){ 26 c.val[i+1]+=c.val[i]/mod; 27 c.val[i]%=mod; 28 } 29 } 30 c.clear(); 31 return c; 32 } 33 NUM operator*(const int x){ 34 NUM a=*this; 35 int ret=0; 36 for(int i=0;i<a.val.size();++i){ 37 a.val[i]*=x; 38 a.val[i]+=ret; 39 ret=a.val[i]/mod; 40 a.val[i]%=mod; 41 } 42 a.val.push_back(ret); 43 a.clear(); 44 return a; 45 } 46 NUM operator*(NUM b) 47 { 48 NUM a=*this,c; 49 int len1=a.val.size(); 50 int len2=b.val.size(); 51 int len3=len1+len2; 52 c.val.resize(len3,0); 53 for(int i=0;i<len1;++i) 54 for(int j=0;j<len2;++j) 55 c.val[i+j]+=a.val[i]*b.val[j]; 56 for(int i=0;i<len3-1;++i){ 57 c.val[i+1]+=c.val[i]/mod; 58 c.val[i]%=mod; 59 } 60 c.clear(); 61 return c; 62 } 63 NUM operator/(const int x){ 64 NUM a=*this,b; 65 int len=a.val.size(); 66 b.val.resize(len,0); 67 for(int i=len-1;i>=1;--i){ 68 b.val[i]=a.val[i]/x; 69 a.val[i-1]+=a.val[i]%x*mod; 70 } 71 b.val[0]=a.val[0]/x; 72 b.clear(); 73 return b; 74 } 75 NUM operator*=(const int x){return *this=*this*x;} 76 NUM operator/=(const int x){return *this=*this/x;} 77 void output(){ 78 int len=val.size(); 79 if(val[len-1]) printf("%d",val[len-1]); 80 for(int i=len-2;i>=0;--i) printf("%08d",val[i]); 81 } 82 }; 83 NUM A(int n,int m) 84 { 85 NUM zero; 86 if(m>n) return zero; 87 NUM ret; 88 ret.val[0]=1; 89 for(int i=n-m+1;i<=n;++i) ret*=i; 90 return ret; 91 } 92 NUM C(int n,int m) 93 { 94 NUM zero; 95 if(m>n) return zero; 96 NUM ret; 97 ret.val[0]=1; 98 for(int i=n-m+1;i<=n;++i) ret*=i; 99 for(int i=1;i<=m;++i) ret/=i; 100 return ret; 101 } 102 int main() 103 { 104 int n,m; 105 scanf("%d%d",&n,&m); 106 if(!n&&!m){ 107 printf("0"); 108 return 0; 109 } 110 NUM ans=A(n,n)*A(n+1,2)*A(n+3,m)+A(n,n)*C(m,1)*A(2,2)*C(n+1,1)*A(n+2,m-1); 111 ans.output(); 112 return 0; 113 }

HNOI 2012/codevs 1994:排隊