zoukankan      html  css  js  c++  java
  • hdu 6836

    hdu 6836

    题解:

    给你一张图求所有生成树的&的期望。

    题解:

    由于求的是 & 那么可以考虑 枚举二进制

    如果答案的二进制中第 i 位 为1, 那么所选的边 所有权值的第i位都为1

    所有可以把答案拆成 二进制的和

    那么就可枚举每个二进制。

    将第i为二进制为1的边组成的生成树设为 (cnti)

    总共的生成树为 (total) 那么期望就是 (cnti* 2^i / total (0 le i le29))

    这里求生成树的个数要用的一个算法就是 生成树计数

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 107;
    
    #define LL long long
    
    const LL MOD = 998244353;
    const LL mod = 998244353;
    
    
    
    LL K[N][N];
    LL gauss(int n){//求矩阵K的n-1阶顺序主子式
        LL res=1;
        for(int i=1;i<=n-1;i++){//枚举主对角线上第i个元素
            for(int j=i+1;j<=n-1;j++){//枚举剩下的行
                while(K[j][i]){//辗转相除
                    int t=K[i][i]/K[j][i];
                    for(int k=i;k<=n-1;k++)//转为倒三角
                        K[i][k]=(K[i][k]-t*K[j][k]+MOD)%MOD;
                    swap(K[i],K[j]);//交换i、j两行
                    res=-res;//取负
                }
            }
            res=(res*K[i][i])%MOD;
        }
        return (res+MOD)%MOD;
    }
    
    struct edge{
        int u, v, w;
    }e[10007];
    
    LL ksm(LL a, LL b) {
        LL base = 1;
        while (b) {
            if (b & 1) {
                base = (base * a) % mod;
            }
            b = b / 2;
            a = a * a % mod;
        }
        return base % mod;
    }
    
    int main(){
    
        int t, n, m;
        scanf("%d", &t);
        while (t--) {
            memset(K, 0, sizeof(K));
            scanf("%d %d", &n, &m);
            for (int i = 1; i <= m; i++) {
                int u, v, w;
                scanf("%d %d %d", &u, &v, &w);
                e[i] = {u, v, w};
                K[u][u]++;
                K[v][v]++;
                K[u][v]--;
                K[v][u]--;
            }
            LL total = gauss(n);
            LL ans = 0;
            LL inv = ksm(total, mod - 2);
            for (int i = 0; i < 30; i++) {
                memset(K, 0, sizeof(K));
                for (int j = 1; j <= m; j++) {
                    if (((1 << i) & e[j].w)) {
                        K[e[j].u][e[j].u]++;
                        K[e[j].v][e[j].v]++;
                        K[e[j].u][e[j].v]--;
                        K[e[j].v][e[j].u]--;
                    }
                }
                LL cnt = (1 << i);
                LL cat = gauss(n);
    
                cnt = (cnt % mod * cat % mod) % mod;
                ans = (ans + cnt) % mod;
            }
            ans = (ans % mod * inv % mod) % mod;
            printf("%lld
    ", ans);
        }
    }
    
  • 相关阅读:
    【线段树】【积累】主席树杂题积累 2016CCPC长春K SequenceII
    【积累】最小不能表示正整数 (以及一些做法
    【字符串】回文树&&回文自动机PAM
    【字符串】后缀自动机SAM
    【字符串】AC自动机
    【字符串】Trie树
    StringUtils类中isEmpty与isBlank的区别
    【Git】pull遇到错误:error: Your local changes to the following files would be overwritten by merge:
    jsp 与jstl
    listener 作用
  • 原文地址:https://www.cnblogs.com/BOZHAO/p/13450052.html
Copyright © 2011-2022 走看看