• 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 }
  • 相关阅读:
    NM_CLICK LVN_ITEMCHANGED
    VI 命令
    ctrlList.GetNextItem(0,LVNI_BELOW) 返回什么值?
    访问空指针一定会使程序死掉吗
    (int)(_tcslen(pDownloadURL)+1)*sizeof(TCHAR);
    MB_OK IDOK
    对于内存管理程序。程序员可能犯的错误是:
    【原创】Windows下Mysql Cluster集群初始化启动方法
    【原创】Windows下Mysql Cluster集群扩容方法
    【原创】如何在LoadRunner测试场景中添加资源监控器
  • 原文地址:https://www.cnblogs.com/12mango/p/7375743.html
Copyright © 2020-2023  润新知