• 组合数学起步-排队[HNOI2012][BZOJ2729]


    <题面>

    这个题十分基础

    写这个博客给自己看的呵呵

    遇到这个题,一看就是组合数学,

    so,开始推公式,

    刚开始想的是,先排男生,再排女生,最后排老师

    推了一会,呃呃呃,情况复杂,考虑的好像有点多。//蒟蒻心态

    然后换了一个思路,

    先排男生,再排老师,最后排女生

    想了下,就决定用减法。


    先把老师和男生混好,然后把女生插空

    这样就会有一种非法情况,老师相连,而且只有一种

    这样就可以把两个老师绑成一个整体,再按上述操作进行

    就会有一个式子:

    $A inom{n+2}{n+2} imes A inom{m}{n+3} -A inom{2}{2} imes A inom{n+1}{n+1} imes Ainom{m}{n+2}$

    还是可以懂得吧?

    而且只要用高精乘低精和高精减就可以了咯

    最后蒻蒻的说:我调这个题主要在高精度上,苦笑

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #define N 50000
     5 using namespace std;
     6 struct Hyper_long{
     7     int *a;
     8     Hyper_long(int k){
     9         a=new int[k];
    10         for(int i=0;i<k;i++)a[i]=0;
    11     }    
    12     void out(){
    13         if(a[0]==0)putchar('0');
    14         for(int i=a[0];i>=1;i--)putchar(a[i]+'0');
    15         puts("");
    16     }
    17     void set_length(int len){
    18         a[0]=len;
    19     }
    20     int length(){
    21         return a[0];
    22     }
    23 };
    24 void operator *= (Hyper_long &x,int y){
    25     long long r=0;
    26     for(int i=1;i<=x.length();i++){
    27         x.a[i]=x.a[i]*y+r;
    28         r=x.a[i]/10;
    29         x.a[i]%=10;
    30     }
    31     while(r!=0){
    32         x.a[0]++;
    33         x.a[x.a[0]]=r;
    34         r=x.a[x.a[0]]/10;
    35         x.a[x.a[0]]%=10;
    36     }
    37     return ;
    38 }
    39 Hyper_long operator - (Hyper_long x,Hyper_long y){
    40     Hyper_long k(N);
    41     int len=max(x.length(),y.length());
    42     for(int i=1;i<=len;i++){
    43         k.a[i]=x.a[i]-y.a[i];
    44         if(k.a[i]<0){
    45             x.a[i+1]--;
    46             k.a[i]+=10;
    47         }
    48     }
    49     while(1){
    50         if(k.a[len]!=0 || len==0) break;
    51         len--;
    52     }
    53     k.set_length(len);
    54     return k;
    55 }
    56 Hyper_long a(N),b(N),c(N);
    57 int m,n;
    58 int main(){
    59     a.a[0]=a.a[1]=1;
    60     b.a[0]=b.a[1]=1;
    61     scanf("%d%d",&n,&m);
    62     for(int i=1;i<=n+2;i++){//先把男生和老师混在一起 
    63         a*=i;
    64     }
    65     for(int i=n+3;i>=n+3-m+1;i--){//把女生插进去 
    66         a*=i;
    67     }
    68     b*=2;//把两个老师绑在一起 
    69     for(int i=1;i<=n+1;i++){//和男生混好
    70         b*=i;
    71     }
    72     for(int i=n+2;i>=n+2-m+1;i--){//把女生插进去 
    73         b*=i;
    74     }
    75     c=a-b;
    76     c.out();//输出 
    77 }
    78 
    
    Total Code

     补:如果可以进行式子的处理然后合并同类项:

    $A inom{n+1}{n+1} imes A inom{m-1}{n+3} imes (n-m+4)-2 imes A inom{n+1}{n+1} imes A inom{m-1}{n+3} imes (n+2)\ = A inom{n+1}{n+1} imes A inom{m-1}{n+3} imes (n+2) imes (n-m+2) $

    就可以实现只用高精乘低精就可以解决的问题了,提出的减法项只用int就可以呢

    Miemeng真的蒻
  • 相关阅读:
    基础薄弱的反思
    最短路SPFA
    乌龟棋
    石子归并
    Linux学习2
    java 基础 数组
    java 基础 异常
    java 基础 接口
    java 基础 instance of
    solidity“abi.encode/abi.encodePacked”使用golang编码
  • 原文地址:https://www.cnblogs.com/kalginamiemeng/p/11109381.html
Copyright © 2020-2023  润新知