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 }

 

posted @ 2017-08-16 20:35  五十岚芒果酱  阅读(134)  评论(0编辑  收藏  举报