题目链接
题意
给出一棵树,每条边有边权。求(sumlimits_{i=1}^n{f(i,j)}),(f(i,j))表示从i到j路径的异或和。
思路
(g_i)表示从根到(i)的异或和,两点之间的路径异或和就可以用(g_i otimes g_j)表示。
先然(g_i)可以一次(dfs)求出来。然后就是统计答案。按位考虑,每一位的数量是当前位置为0的个数与1的个数的成绩,再乘以当前位置的贡献即可。
代码
/* * @author: wxyww * @date: 2019-06-05 07:59:07 * @last modified time: 2019-06-05 08:30:46 */ #include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<algorithm> #include<queue> #include<vector> #include<ctime> using namespace std; typedef long long ll; const int n = 100000 + 100,mod = 1000000007; ll read() { ll x=0,f=1;char c=getchar(); while(c<'0'||c>'9') { if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); } return x*f; } int f[2][100],b[n]; struct node { int u,v,w,nxt; }e[n]; int ejs,head[n]; void add(int u,int v,int w) { e[++ejs].v = v;e[ejs].nxt = head[u];head[u] = ejs;e[ejs].w = w; } void dfs(int u) { for(int i = head[u];i;i = e[i].nxt) { int v = e[i].v; b[v] = b[u] ^ e[i].w; dfs(v); } } void solve(int x) { for(int i = 0;i <= 20;++i) f[(x >> i) & 1][i]++; } int main() { int n = read(); for(int i = 2;i <= n;++i) { int u = read(),w = read(); add(u,i,w); } dfs(1); ll ans = 0; for(int i = 1;i <= n;++i) solve(b[i]); for(int i = 0;i <= 20;++i) ans += 1ll * f[0][i] * f[1][i] % mod * (1 << i) % mod,ans %= mod; cout<<ans * 2 % mod; return 0; }
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/603143.html