zoukankan      html  css  js  c++  java
  • 2019牛客暑期多校训练营(第九场)E All men are brothers(并查集+组合数学)

    题目链接:https://ac.nowcoder.com/acm/contest/889/E

    题目大意:从n个人中选出4个不能互相是朋友的方案数,每轮会有一对成为朋友,回答m个询问。

    解题报告:设合并集合x和集合y,对于剩下的部分z为n-sz[x]-sz[y],对于前一次的方案,我们要减掉

      1.x集合中选1个人,y集合中选2个人,z中1个人

      2.x集合中选2个人,y集合中选1个人,z中1个人

      3.x集合中选2个人,y集合中选2个人,z中0个人

      这三种情况。

      所以可以通过维护一个选2人的组合数来解决。

      codeblock没法编译int128类型的,所以求组合数就只好通过打表解决了。

    AC代码:

     1 #include<bits/stdc++.h>
     2 #define numm ch-48
     3 #define pd putchar(' ')
     4 #define pn putchar('
    ')
     5 #define pb push_back
     6 #define fi first
     7 #define se second
     8 #define fre1 freopen("1.txt","r",stdin)
     9 #define fre2 freopen("2.txt","w",stdout)
    10 #define debug(args...) cout<<#args<<"->"<<args<<"
    ";
    11 using namespace std;
    12 template <typename T>
    13 void read(T &res) {
    14     bool flag=false;char ch;
    15     while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true);
    16     for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
    17     flag&&(res=-res);
    18 }
    19 template <typename T>
    20 void write(T x) {
    21     if(x<0) putchar('-'),x=-x;
    22     if(x>9) write(x/10);
    23     putchar(x%10+'0');
    24 }
    25 typedef long long ll;
    26 typedef unsigned long long ull;
    27 const int maxn=100010;
    28 const int maxm=505;
    29 const int mod=1e9+7;
    30 const int inv2=500000004;
    31 int f[maxn],sz[maxn];
    32 ll c[maxn][5];
    33 int getf(int v) {
    34     return f[v]==v?v:(f[v]=getf(f[v]));
    35 }
    36 void init() {
    37     c[0][0]=1;
    38     for(int i=1;i<=maxn-10;i++) {
    39         c[i][0]=1;
    40         for(int j=1;j<=min(i,4);j++)
    41             c[i][j]=c[i-1][j]+c[i-1][j-1];
    42     }
    43 }
    44 int main()
    45 {
    46 //    #define local
    47     #ifdef local
    48         fre1;
    49 //        fre2;
    50     #endif // local
    51     int n,m;
    52     init();
    53     read(n),read(m);
    54     for(int i=1;i<=n;i++)
    55         sz[i]=1,f[i]=i;
    56     ll c2=c[n][2];    ///维护一个取两个数的组合数
    57     ll ans=c[n][4];
    58     write(ans);pn;
    59     while(m--) {
    60         int a,b;
    61         read(a),read(b);
    62         int x=getf(a);
    63         int y=getf(b);
    64         if(x==y) {
    65             write(ans);pn;
    66             continue;
    67         }
    68         ll num=n-sz[x]-sz[y];
    69         ll temp=c2-sz[x]*num-sz[y]*num-sz[x]*sz[y];///减去不满足的情况
    70         ans-=sz[x]*sz[y]*temp;  ///temp为z中取2个人的合法情况,现在x和y为一伙人,要减掉这种情况
    71         c2-=sz[x]*sz[y];        ///减去两个集合各取一个的情况
    72         f[x]=y;
    73         sz[y]+=sz[x];
    74         write(ans);pn;
    75     }
    76     return 0;
    77 }
    代码在这里!
  • 相关阅读:
    MySQL之索引
    MySQL之用户权限及pymysql
    Vue初识
    input标签的accept属性、JQuery绑定keyDown事件
    给bootstrap-sweetalert弹框的按钮绑定事件
    JavaScript FormData对象,FileReader对象,files属性
    Django CBV加装饰器、Django中间件、auth模块
    Django session和cookie
    Django form组件
    Django ajax的简单使用、自定义分页器
  • 原文地址:https://www.cnblogs.com/wuliking/p/11363519.html
Copyright © 2011-2022 走看看