HNOI 2012/codevs 1994:排队
题目描述 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 }