zoukankan      html  css  js  c++  java
  • 2020杭电多校第六场 hdu6836 Expectation

    睡不着 , 水发题解吧

    题目链接

    http://acm.hdu.edu.cn/showproblem.php?pid=6836

    题目大意

    给定 N 个点 M 条边的无相连通图

    定义图的生成树的值为该生成树所有边权按位与的值

    问这张图的生成树的期望值是多少

    解题思路 

    定义原图的生成树的个数为 SUM

    因为要进行位运算 , 所以往二进制的角度思考

    我们将每条边的边权转换为二进制数

    那么答案的二进制数第 i 位的期望值会是多少呢

    很显然只有当生成树的每条边的第 i 位都为 1 时才会对答案产生贡献 ( &运算 )

    于是我们可以将第 i 位为 1 的边取出来重新建图

    并且计算新建的图的生成树的个数 , 记为 NOW

    那么答案的二进制数第 i 位的期望值就为 $dfrac{now}{sum} imes ( 1 < < i) $

    简单模拟一下即可 ( 生成树的个数用 Matrix Tree 计算)

    AC_Code

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N = 2e2 + 10 , mod = 998244353;
    const double eps = 1e-12;
    int G[N][N];
    int n , m;
    int pow_mod(int x , int n , int mod)
    {
        int res = 1;
        while(n)
        {
            if(n & 1) res = res * x % mod;
            x = x * x % mod;
            n >>= 1;
        }
        return res;
    }
    int dcmp(int x)
    {
        if(x <= eps || x >= -eps) return 0;
        else return x < 0 ? -1 : 1;
    }
    int Gauss(int n)
    {
        int ans = 1;
        for(int i = 1 ; i < n ; i ++)
        {
            for(int k = i + 1 ; k < n ; k ++)
            {
                while(G[k][i])
                {
                    int d = G[i][i] / G[k][i];
                    for(int j = i ; j < n ; j ++) G[i][j] = (G[i][j] - 1LL * d * G[k][j] % mod + mod) % mod;
                    swap(G[i] , G[k]) , ans = -ans;
                }
            }
            ans = 1LL * ans * G[i][i] % mod , ans = (ans + mod) % mod;
        }
        return ans;
    }
    void init(int n)
    {
        memset(G , 0 , sizeof(G));
    }
    vector<pair<int , int>>vec[50];
    signed main()
    {
        ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0);
        int T = 1;
        cin >> T;
        while(T --)
        {
            for(int i = 0 ; i <= 32 ; i ++) vec[i].clear();
            cin >> n >> m;
            for(int i = 1 ; i <= m ; i ++)
            {
                int x , y , w;
                cin >> x >> y >> w;
                G[x][x] ++ , G[y][y] ++;
                G[x][y] -- , G[y][x] --;
                for(int j = 32 ; ~j ; j --) if((w >> j) & 1) vec[j].push_back(make_pair(x , y));
            }
            int tot = Gauss(n) , ans = 0;
            int p = pow_mod(tot , mod - 2 , mod);
            for(int j = 0 ; j <= 32 ; j ++)
            {
                init(n);
                for(auto i : vec[j])
                {
                    int x = i.first , y = i.second;
                    G[x][x]++;
                    G[y][y]++;
                    G[x][y]--;
                    G[y][x]--;
                }
                int now = Gauss(n);
                ans += ((1ll << j) % mod) * now % mod * p;
                ans %= mod;
            }
            cout << ans << '
    ';
        }
        return 0;
    }
  • 相关阅读:
    数据结构>堆栈的使用 小强斋
    数据结构>图的存储结构 小强斋
    数据结构>图的基本术语 小强斋
    java使用JNDI 获取weblogic配置的数据源 连接数据库 小强斋
    java使用JNDI 获取weblogic配置的数据源 连接数据库 小强斋
    数据结构>队列 小强斋
    C++实现平方的安全方法(redis的实现)
    jmeter性能测试使用示例
    redis学习总结1
    java NIO使用示例
  • 原文地址:https://www.cnblogs.com/StarRoadTang/p/13450197.html
Copyright © 2011-2022 走看看