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
题解:
组合数学+高精度。。。。。
先将男生排序
分两种情况
1.将两个老师看成一个人,放在男生里面,这时两个老师之间必须放一个女生,剩下的女生放再其他可以放的位子
2.两个老师分别用男生隔开,在把女生放进去
ans=n!(2(n+1)*A(n+2,m-1)+n*(n+1)*A(n+3,m))
=(n+1)!A(n+2,m-1)(n2+3n+2m)
code:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #define MAXN 3000 7 #define maxnum 10000 8 using namespace std; 9 char ch; 10 bool ok; 11 void read(int &x){ 12 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; 13 for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); 14 if (ok) x=-x; 15 } 16 struct bignum{ 17 int len,v[MAXN]; 18 bignum(){memset(v,0,sizeof(v)),len=1;} 19 bignum operator=(const char* num){ 20 memset(v,0,sizeof(v)); 21 len=((strlen(num)-1)>>2)+1; 22 int j=1,k=0; 23 for (int i=strlen(num)-1;i>=0;i--){ 24 if (j==maxnum) j=1,k++; 25 v[k]+=(num[i]-'0')*j; 26 j*=10; 27 } 28 } 29 bignum operator=(const int num){ 30 char a[MAXN<<2]; 31 sprintf(a,"%d",num); 32 *this=a; 33 return *this; 34 } 35 bignum (int num){*this=num;} 36 bignum (const char* num){*this=num;} 37 bignum operator+(const bignum &a){ 38 bignum c; 39 c.len=max(len,a.len); 40 for (int i=0;i<c.len;i++){ 41 c.v[i]+=v[i]+a.v[i]; 42 if (c.v[i]>=maxnum) c.v[i+1]+=(c.v[i]/maxnum),c.v[i]%=maxnum; 43 } 44 while (c.v[c.len]) c.len++; 45 return c; 46 } 47 bignum operator-(const bignum b){ 48 bignum a,c; 49 a=*this; 50 c.len=len; 51 for (int i=0;i<len;i++){ 52 if (a.v[i]<b.v[i]) a.v[i+1]--,a.v[i]+=maxnum; 53 c.v[i]=a.v[i]-b.v[i]; 54 } 55 while (c.len>1&&!(c.v[c.len-1])) c.len--; 56 return c; 57 } 58 bignum operator*(const bignum &a){ 59 bignum c; 60 c.len=len+a.len; 61 for (int i=0;i<len;i++) 62 for (int j=0;j<a.len;j++){ 63 c.v[i+j]+=v[i]*a.v[j]; 64 if (c.v[i+j]>=maxnum) c.v[i+j+1]+=(c.v[i+j]/maxnum),c.v[i+j]%=maxnum; 65 } 66 while (c.len>1&&!(c.v[c.len-1])) c.len--; 67 return c; 68 } 69 bignum operator*(const int &a){ 70 bignum c=a; 71 return *this*c; 72 } 73 /* 74 inline bignum operator*(const int &a){ 75 bignum c; 76 c.len=len; 77 for (int i=0;i<len;i++){ 78 c.v[i]+=v[i]*a; 79 if (c.v[i]>=maxnum) c.v[i+1]=(c.v[i]/maxnum),c.v[i]%=maxnum; 80 } 81 if (c.v[c.len]) c.len++; 82 return c; 83 } 84 */ 85 bignum operator/(const int &b){ 86 bignum c; 87 int x=0; 88 for (int i=len-1;i>=0;i--){ 89 c.v[i]=(x*maxnum+v[i])/b; 90 x=(x*maxnum+v[i])%b; 91 } 92 c.len=len; 93 while (c.len>1&&!(c.v[c.len-1])) c.len--; 94 return c; 95 } 96 bignum operator+=(const bignum &a){*this=*this+a;return *this;} 97 bignum operator-=(const bignum &a){*this=*this-a;return *this;} 98 bignum operator*=(const bignum &a){*this=*this*a;return *this;} 99 bignum operator/=(const int &a){*this=*this/a;return *this;} 100 bool operator < (const bignum &x)const{ 101 if (len!=x.len) return len<x.len; 102 for (int i=len-1;i>=0;i--) 103 if (v[i]!=x.v[i]) return v[i]<x.v[i]; 104 return false; 105 } 106 bool operator > (const bignum &x)const{return x<*this;} 107 bool operator <=(const bignum &x)const{return !(x<*this);} 108 bool operator >=(const bignum &x)const{return !(*this<x);} 109 bool operator ==(const bignum &x)const{return !(x<*this||*this<x);} 110 bool operator !=(const bignum &x)const{return x<*this||*this<x;} 111 }ans,tmp; 112 void write(bignum x){ 113 printf("%d",x.v[x.len-1]); 114 for (int i=x.len-2;i>=0;i--) printf("%0*d",4,x.v[i]); 115 } 116 int n,m; 117 int main(){ 118 read(n),read(m); 119 ans=n*n+3*n+2*m; 120 for (int i=1;i<=n+1;i++) ans=ans*i; 121 for (int i=n-m+4;i<=n+2;i++) ans=ans*i; 122 write(ans); 123 return 0; 124 }