zoukankan      html  css  js  c++  java
  • P3223 [HNOI2012]排队

    题目描述

    某中学有 n 名男同学,m 名女同学和两名老师要排队参加体检。他们排成一条直线,并且任意两名女同学不能相邻,两名老师也不能相邻,那么一共有多少种排法呢?(注意:任意两个人都是不同的)

    输入输出格式

    输入格式:

    只有一行且为用空格隔开的两个非负整数 n 和 m,其含义如上所述。 对于 30%的数据 n<=100,m<=100 对于 100%的数据 n<=2000,m<=2000

    输出格式:

    输出文件 output.txt 仅包含一个非负整数,表示不同的排法个数。注意答案可能很大。

    输入输出样例

    输入样例#1: 
    1  1
    输出样例#1: 
    12

    Solution:

      本题组合数学+高精度。

      冷静分析。。。

      首先$n$个男生的全排列为$A(n,n)$,在形成的$n+1$个空中插入两名老师方案数为$A(n+1,2)$,新形成的$n+3$个空中选择$m$个插入女生方案数为$A(n+3,m)$。

      注意到上面的情况并没有包含两名老师夹一个女生的情况,我们需要补上该情况的方案:把两名老师和一个女生看作整体,有$A(2,2)*m$种方案,然后把这个整体插入到$n+1$个空中有$A(n+1,1)$种方案,最后的$m-1$个女生插入到$n+2$个空中方案数为$A(n+2,m-1)$。

      综上所述,总的方案数为$A(n,n)*A(n+1,2)*A(n+3,m)+m*A(2,2)*A(n+1,1)*A(n+2,m-1)$,然后需要用到高精度加法和乘法,结构体重载运算符就好了。

    代码:

    /*Code by 520 -- 9.13*/
    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define RE register
    #define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
    #define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
    using namespace std;
    const ll N=5005,Base=1e8;
    ll n,m;
    struct node{
        ll a[N],len;
        il void Clr(){memset(a,0,sizeof a),len=0;}
        il void Push(int x){a[len=1]=x;}
        node operator * (const node &X) const{
            node tp;tp.Clr();tp.len=len+X.len+10;
            For(i,1,len) For(j,1,X.len) {
                tp.a[i+j-1]+=a[i]*X.a[j];
                tp.a[i+j]+=tp.a[i+j-1]/Base;
                tp.a[i+j-1]%=Base;
            }
            For(i,1,tp.len) tp.a[i+1]+=tp.a[i]/Base,tp.a[i]%=Base;
            while(tp.len&&!tp.a[tp.len]) tp.len--;
            return tp;
        }
        node operator + (const node &X) const{
            node tp;tp.Clr();tp.len=max(len,X.len)+10;
            For(i,1,tp.len){
                tp.a[i]+=a[i]+X.a[i];
                tp.a[i+1]+=tp.a[i]/Base;
                tp.a[i]%=Base;
            }
            For(i,1,tp.len) tp.a[i+1]+=tp.a[i]/Base,tp.a[i]%=Base;
            while(tp.len&&!tp.a[tp.len]) tp.len--;
            return tp;
        }
        il void Output(){
            printf("%lld",a[len]);
            Bor(i,1,len-1) printf("%08lld",a[i]);
        }
    }ans;
    
    il node A(ll n,ll m){
        node res,tp;res.Clr(),tp.Clr(),res.Push(1);
        if(!m) return res;
        if(m>n) {ans.Clr();return res;}
        For(i,n-m+1,n) tp.Push(i),res=res*tp;
        return res;
    }
    
    int main(){
        cin>>n>>m;
        if(!n&&!m) cout<<0,exit(0);
        ans=A(n,n)*A(n+1,2)*A(n+3,m)+A(n,n)*A(n+1,1)*A(2,2)*A(m,1)*A(n+2,m-1);
        ans.Output();
        return 0;
    }
  • 相关阅读:
    Composition API
    Vue通讯
    pc-H5 适配方案
    Mac Chrome浏览器跨域指令快速启动应用创建,避免每次在终端输入指令
    datatables 添加title属性
    元素的显示与隐藏
    【前端】跨浏览器事件处理程序EventUtil.js个人注释及详解
    【前端】javascript+jQuery实现旋转木马效果轮播图slider
    【前端】javascript+jquery实现手风琴式的滚动banner或产品展示图
    【前端】javascript实现带有子菜单和控件的轮播图slider
  • 原文地址:https://www.cnblogs.com/five20/p/9651212.html
Copyright © 2011-2022 走看看