赞
踩
题意:给你一棵树,问所有路径(不重复)上边权的异或和。
思路:我很想说它是一题套路题,当我确实没有把它转换出来。。。。
这里直接给出官方题解上的思路
从而转换为我们熟悉的按位算贡献问题。依次枚举每一位,最多是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; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。