zoukankan      html  css  js  c++  java
  • AtCoder Regular Contest 93

    Contest Link

    正好想打场AT,然后模拟赛又出了这场的 F 题,于是就做了……

    E - Bichrome Spanning Tree

    给定一个 (n)(m) 边无向图,对边黑白染色,使得满足包含两种颜色的最小生成树的权值和为 (X) .


    首先求出原图的最小生成树,设权值和为 (ans_0) ,如果 (ans_0>X) 显然无解。

    否则,依次枚举每条边并钦定选择,计算出这种情况下的最小生成树权值。记其中 (=X) 的个数为 (cnt_1)(>X) 的个数为 (cnt_2)

    如果 (ans_0<X) ,答案是 (2(2^{cnt_1}-1) imes2^{cnt_2})(2) 是原 MST 的染色方式;(2^{cnt_1}-1)(s=X) 的强制选择情况中的染色方式,因为至少有一条边要和原 MST 不同;(2^{cnt_2})(s>X) 的染色方式,任意染色。

    如果 (ans_0=X) ,那么答案就是 ((2^{cnt_1}-2) imes2^{cnt_2})

    //Author: RingweEH
    ll Kruskal( int chos )
    {
        ll res=0; int fx,fy;
        for ( int i=0; i<=n+1; i++ ) fa[i]=i;
        if ( chos ) { fx=find(e[chos].fro),fy=find(e[chos].to); fa[fx]=fy; res+=e[chos].val; }
        for ( int i=1; i<=m; i++ )
        {
            if ( i==chos ) continue;
            fx=find(e[i].fro); fy=find(e[i].to);
            if ( fx^fy ) fa[fx]=fy,res+=e[i].val;
        }
        return res;
    }
    
    int main()
    {
        n=read(); m=read(); X=read();
        for ( int i=1; i<=m; i++ ) e[i].fro=read(),e[i].to=read(),e[i].val=read();
    
        sort(e+1,e+1+m); ll ans0=Kruskal(0);
        if ( ans0>X ) { puts("0"); return 0; }
        int cnt1=0,cnt2=0;
        for ( int i=1; i<=m; i++ )
        {
            ll s=Kruskal(i);
            if ( s==X ) cnt1++;
            else if ( s>X ) cnt2++;
        }
    
        if ( ans0==X ) printf("%lld
    ",(power(2,cnt1)+Mod-2)%Mod*power(2,cnt2)%Mod );
        else printf("%lld
    ",(2ll*power(2ll,cnt1)+Mod-2)%Mod*power(2,cnt2)%Mod );
    
        return 0;
    }
    

    F - Dark Horse

    (2^N) 个人,二叉树形式进行淘汰赛,一开始的顺序是 (2^N) 的任意一个排列。有 (M) 个人 (A_1sim A_M) 打得过 (1)(1) 能打得过其他所有人,如果对决中没有 (1) 那么编号小的获胜。求所有情况中 (1) 最终胜利的数量。


    (1) 要赢,必须打败来自大小为 (2^0sim 2^{n-1}) 的子树的 (n) 个对手,走到二叉树顶端。

    问题转化为:将 (2sim 2^n) 划分成 (n) 个集合,第 (i) 个大小为 (2^{i-1}) ,每个集合中的 (min) 不是 (M) 个人中的一个。

    考虑容斥,对于一个状态 (S) ,第 (i-1) 位为 (1) 表示第 (i) 个集合的 (min)(M) 个人之一。DP 预处理即可。注意这里是钦定 (1) 在第一个位置了,而 (1) 在其他位置等价,所以要乘上 (2^n) .

    组合数没判 (n<m) 于是就喜提 RE ……

    //Author: RingweEH
    int power(int a,int b)	//quick power
    void Init( int n )		//Init fac,infac
    int binom( int n,int m ) { return (n<m) ? 0 : 1ll*fac[n]*infac[m]%Mod*infac[n-m]%Mod; }
    void bmod( int &x,int y ) { x+=y-Mod; x+=(x<0)*Mod; }
    
    signed main()
    {
        n=read(); m=read(); int lim=(1<<n);
        for ( int i=1; i<=m; i++ ) a[i]=read();
    
        reverse(a+1,a+1+m); Init(lim);
        dp[0][0]=1;
        for ( int i=1; i<=m; i++ )
            for ( int S=0; S<lim; S++ )
            {
                bmod(dp[i][S],dp[i-1][S]);
                for ( int k=0; k<n; k++ )
                    if ( !(S>>k&1) ) 
                        bmod(dp[i][S|(1<<k)],1ll*dp[i-1][S]*binom(lim-a[i]-S,(1<<k)-1)%Mod);
            }
        ans=0;
        for ( int i=0; i<lim; i++ )
        {
            int S=lim-1-i;
            for ( int j=0; j<n; j++ )
                if ( !(i>>j&1) ) dp[m][i]=1ll*dp[m][i]*binom(S,1<<j)%Mod,S-=1<<j;
            if ( __builtin_popcount(i)&1 ) bmod(ans,Mod-dp[m][i]);
            else bmod(ans,dp[m][i]);
        }
    
        ans=1ll*lim*ans%Mod;
        for ( int i=0; i<n; i++ ) ans=1ll*ans*fac[1<<i]%Mod;
        printf("%d
    ",ans );
    
        return 0;
    }
    
    天光渐亮。
  • 相关阅读:
    GreenPlum 大数据平台--运维(二)
    GreenPlum 大数据平台--运维(一)
    GreenPlum 大数据平台--非并行备份(六)
    zabbix--高级篇-监控docker服务(一)
    GreenPlum 大数据平台--备份-邮件配置-gpcrondump & gpdbrestore(五)
    subprocess模块
    Python写随机发红包的原理流程
    粘包
    网络编程: 基于UDP协议的socket
    网络编程: 基于TCP协议的socket, 实现一对一, 一对多通信
  • 原文地址:https://www.cnblogs.com/UntitledCpp/p/ARC093.html
Copyright © 2011-2022 走看看