当前位置:   article > 正文

Mynavi Programming Contest 2021(AtCoder Beginner Contest 201)E - Xor Distances_mynavi programming contest 2021(atcoder beginner c

mynavi programming contest 2021(atcoder beginner contest 201)

传送门

题意:给你一棵树,问所有路径(不重复)上边权的异或和。

思路:我很想说它是一题套路题,当我确实没有把它转换出来。。。。
这里直接给出官方题解上的思路在这里插入图片描述
从而转换为我们熟悉的按位算贡献问题。依次枚举每一位,最多是2^60 - 1 枚举到第60位就行(其实这个无所谓,比最大值大就行),因为是选择两个dis(x,i),故只有出现 1 0 的情况才能对结果做出贡献。

#include<bits/stdc++.h>
using namespace std;


typedef long long LL;
typedef pair<int, int> P;

const int maxn = 2e5 + 10;
const LL INF = 1e18;
const double eps = 1e-6;
const LL mod = 1e9 + 7;

struct edge{
    int to;
    LL cost;
    edge(int tt = 0, LL cc = 0) : to(tt), cost(cc) {} 
};

int n;
LL d[maxn];
vector<edge> g[maxn];

void dfs(int u, int f) {
    for(int i = 0; i < g[u].size(); i++) {
        int v = g[u][i].to;
        if(v == f) continue;
        d[v] = d[u]^g[u][i].cost;
        dfs(v, u);
    }
}

//按位算贡献

void solve() {
    cin >> n;
    int v, u; 
    LL w;
    for(int i = 1; i < n; i++) {
        cin >> v >> u >> w;
        g[v].emplace_back(edge(u, w));
        g[u].emplace_back(edge(v, w));
    }
    dfs(1, 1);
    LL ans = 0;
    for(int i = 0; i <= 60; i++) {
        int cnt[2] = {0};
        for(int j = 1; j <= n; j++) cnt[(d[j] >> i) & 1L]++;
        ans += ((1LL << i) %mod * (cnt[0] %mod * cnt[1] % mod)) % mod;
        ans %= mod;
    } 
    cout << ans << endl;
}

int main() {
    ios::sync_with_stdio(false);
    solve();
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/52645
推荐阅读
相关标签
  

闽ICP备14008679号