题目大意是让你求 dist(i,j) 1 <= i < j <= n
dist(i,j)为一条路径 i ~ j所有权值的异或和
我们首先将 一个点 到其他所有点的 异或求出来 就可以将题目转换为
dist(i) ^ dist(j) 1 <= i < j <= n 这个是n^2的 超时考虑如何优化
看了题解 才知道 只需要求 每一位的 贡献值 即可
若 第k位是 有贡献的 那么 dist(i)的第k位 和 dist(j)的第k位 一定是不同的
所以只需要计算出 i 位 为 0的个数 和 i位 为1的个数即可计算出 i位的贡献
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
using namespace std;
const int N = 2e5 + 10,M = N * 2,mod = 1e9 + 7;
typedef long long ll;
int head[N],to[M],last[M];ll w[M];int cnt;
void add(int a,int b,ll c){
to[++cnt] = b;
w[cnt] = c;
last[cnt] = head[a];
head[a] = cnt;
}
ll dist[N];
void dfs(int x,int lastt){
for(int i = head[x]; i != -1; i = last[i]){
int j = to[i];
if(j == lastt) continue;
dist[j] = dist[x] ^ w[i];
dfs(j,x);
}
}
int main(){
int n;
memset(head,-1,sizeof head);
cin >> n;
for(int i = 1; i <= n - 1; i++){
int x,y;ll w;
cin >> x >> y >> w;
--x,--y;
add(x,y,w);
add(y,x,w);
}
dfs(0,-1);
ll ans = 0;
for(int i=0; i<60; i++){
vector<int> s(2);
for(int j=0; j<n; j++) s[dist[j]>>i&1]++;
ans += (1ll<<i)%mod*s[0]%mod*s[1];
ans %= mod;
}
cout << ans <<endl;
return 0;
}