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);
        }
    }
    
  • 相关阅读:
    Android 基于Message的进程间通信 Messenger完全解析
    Android获取TextView显示的字符串宽度
    关于移动App的五个提问
    Android 结合实例学会AsyncTask的用法
    提高 Android 代码质量的4个工具
    高效开发Android App的10个建议
    移动5年 Android生态系统的演进
    最受欢迎的游戏引擎集结号:跨平台篇
    Java程序员转Android开发必读经验分享
    8 个最优秀的 Android Studio 插件
  • 原文地址:https://www.cnblogs.com/BOZHAO/p/13450052.html
Copyright © 2011-2022 走看看