zoukankan      html  css  js  c++  java
  • 【2020杭电多校】第六场 Expectation 矩阵树定理

    Expectation

    题意

    给出一个 n 个点,m 条边的无向图,现在随机选择一颗生成树,一颗生成树的价值为边权的 & 和。

    问生成树价值的期望是多少?

    思路

    ​ 按位考虑,枚举所有边,如果当前边权的二进制的第 i 位为 1 ,把这条边放到图中,然后使用矩阵树定理求生成树的数量。

    ​ 答案(rel = sum_{i=0}^{31}num_i*(1<<i)*sum^{-1}),sum表示整个图的生成树数量,(num_i)表示枚举第 i 位时生成树的数量

    代码

    #include <bits/stdc++.h>
    #define fuck system("pause")
    #define emplace_back push_back
    #define pb push_back
    using namespace std;
    typedef long long ll;
    const ll mod = 998244353;
    const double eps = 1e-6;
    const ll inf = 0x3f3f3f3f;
    const ll N = 2e5 + 10;
    
    ll mat[110][110];
    struct Edge{
        ll u, v, w;
    } edge[N];
    
    ll gauss(ll n){
        ll ans = 1;
        for (ll i = 1; i < n;i++){
            for (ll j = i + 1; j < n; j++) {
                while(mat[j][i]){
                    ll t = mat[i][i] / mat[j][i];
                    for (ll k = i; k < n;k++){
                        mat[i][k] = (mat[i][k] - t * mat[j][k] + mod) % mod;
                    }
                    swap(mat[i], mat[j]);
                    ans = -ans;
                }
            }
            ans = (ans * mat[i][i]) % mod;
        }
        return (ans + mod) % mod;
    }
    
    ll qpow(ll a, ll b)
    {
        ll ans = 1;
        a %= mod;
        while (b) {
            if (b & 1) {
                ans = (ans * a) % mod;
            }
            b >>= 1;
            a = a * a % mod;
        }
        return ans % mod;
    }
    
    int main(){
        ll T;
        scanf("%lld", &T);
        while(T--){
            ll n,m;
            scanf("%lld%lld", &n, &m);
            memset(mat, 0, sizeof(mat));
            for (ll i = 1; i <= m;i++){
                scanf("%lld%lld%lld", &edge[i].u, &edge[i].v, &edge[i].w);
            }
            ll ans = 0;
            for (ll i = 0; i < 32;i++){
                memset(mat, 0, sizeof(mat));
                for (ll j = 1; j <= m;j++){
                    if(edge[j].w&(1<<i)){
                        ll u = edge[j].u, v = edge[j].v;
                        mat[u][u]++, mat[v][v]++;
                        mat[u][v]--, mat[v][u]--;
                    }
                }
                ll num = gauss(n);
                ans = (ans + (1 << i) * num % mod) % mod;
            }
            memset(mat, 0, sizeof(mat));
            for(ll i=1;i<=m;i++){
                ll u = edge[i].u, v = edge[i].v;
                mat[u][u]++, mat[v][v]++;
                mat[u][v]--, mat[v][u]--;
            }
            printf("%lld
    ", ans * qpow(gauss(n), mod - 2) % mod);
        }
        return 0;
    }
    

  • 相关阅读:
    Add Two Numbers
    Reverse Linked List II
    Reverse Linked List
    Remove Duplicates from Sorted List
    Remove Duplicates from Sorted List II
    Partition List
    Intersection of Two Linked Lists
    4Sum
    3Sum
    2Sum
  • 原文地址:https://www.cnblogs.com/valk3/p/13456676.html
Copyright © 2011-2022 走看看