Mynavi Programming Contest 2021(AtCoder Beginner Contest 201)E - Xor Distances

传送门

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

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

#include
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;
}

你可能感兴趣的:(暴力,思维,构造)