2020杭电多校6 Expectation

Expectation

题意:
给一个n个点m条边的无向图,定义生成树的权值为树上所有边权的与和,问随机选择一个生成树的权值的期望是多少

做法:
matrix-tree + 边权的二进制枚举

点击查看代码块
#include <bits/stdc++.h>

#define ed end()
#define bg begin()
#define mkp make_pair
#define pb push_back
#define v(T) vector<T>
#define all(x) x.bg,x.ed
#define newline puts("")
#define si(x) ((int)x.size())
#define rep(i,n) for(int i=1;i<=n;++i)
#define rrep(i,n) for(int i=0;i<n;++i)
#define srep(i,s,t) for(int i=s;i<=t;++i)

using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 1e5+10;
const int inf = 0x7f7f7f7f;
const ll inf_ll = 1ll*inf*inf;
const int Mod = 998244353;
const double eps = 1e-7;


struct node {
    int x, y, w;
} e[maxn];
int T;
ll K[110][110];
ll mypow(ll a, ll b) {
    ll ret = 1;
    while (b) {
        if (b & 1) ret = ret * a % Mod;
        a = a * a % Mod;
        b >>= 1;
    }
    return ret;
}
ll gauss(int n) {//高斯消元
    ll res = 1;
    for (int i = 1; i <= n - 1; 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] - 1ll * t * K[j][k] % Mod + Mod) % Mod;
                swap(K[i], K[j]);
                res = -res;
            }
        }
        res = (res * K[i][i]) % Mod;
        res = (res + Mod) % Mod;
    }
    return (res + Mod) % Mod;
}
int main() {
    scanf("%d", &T);
    while (T--) {
        int n, m;
        scanf("%d%d", &n, &m);
        memset(K, 0, sizeof(K));
        for (int i = 1; i <= m; i++) {
            int x, y, w;
            scanf("%d%d%d", &x, &y, &w);
            K[x - 1][x - 1]++;
            K[y - 1][y - 1]++;
            K[x - 1][y - 1]--;
            K[y - 1][x - 1]--;
            e[i] = node{x, y, w};
        }
        ll base = gauss(n);//求出所有生成树的个数
        base = mypow(base, Mod - 2);//作为分母,求逆元
        ll ans = 0;
        for (int i=0;i<=30;i++){//枚举二进制的每一位
            memset(K, 0, sizeof(K));
            rep(j,m)//计算每条边权值的贡献
                if (e[j].w >> i & 1) {
                    node it = e[j];
                    K[it.x - 1][it.x - 1]++;
                    K[it.y - 1][it.y - 1]++;
                    K[it.x - 1][it.y - 1]--;
                    K[it.y - 1][it.x - 1]--;
                }
            ans += (1ll << i) % Mod * gauss(n) % Mod ;
            ans %= Mod;
        }
        ans = (ans * base) % Mod;
        printf("%lld\n", ans);
    }
    return 0;
}
posted @ 2020-08-13 11:59  wsl_lld  阅读(150)  评论(0编辑  收藏  举报