ABC201E Xor Distances 题解
ABC201E Xor Distances 题解
题目大意#
给定一个带权树,求树上每两点的简单路径上的边权的异或和的和。
形式化的,定义 为 到 的简单路径上的边权的异或和,求 。
Solve#
令 。
指定 为根,考虑先 dfs 遍历树求出 ,然后换根 。
若已知 ,对于 ,我们分两部分考虑,即在子树 中的 集合和不在子树 中的 集合。
- 对于 中的点,根从 转移到 ,他们到根的路径的异或和会多异或上 。
- 对于 中的店,他们到根的路径的异或和会少异或上 ,由于异或的自反性,通过再异或上一个 也可以实现。
综上, 即为 的每一项异或上 的和,即 。
考虑如何计算。
不难想到:用 记录下 的每一项 二进制下 和 的个数,按位枚举 ,若其第 位为 ,则 后第 位会与原来相反,所以此时交换 和 。
经过交换后,我们有 。本题 ,故 。
答案即为 。
Code#
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
short f=1;
int x=0;
char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
#define mod 1000000007
int n,cnt[60][2],ans,mi[60]={1};
#define PII pair<int,int>
vector<PII>e[200010];
void dfs1(int u,int d,int fa)
{
for(int i=59;i>=0;i--) cnt[i][d>>i&1]++;
for(auto i:e[u])
if(i.first!=fa) dfs1(i.first,d^i.second,u);
}
void dfs2(int u,int fa)
{
for(int i=59;i>=0;i--) ans=(ans+mi[i]*cnt[i][1]%mod)%mod;
for(auto i:e[u])
if(i.first!=fa)
{
for(int j=59;j>=0;j--)
if(i.second>>j&1)
swap(cnt[j][1],cnt[j][0]);
dfs2(i.first,u);
for(int j=59;j>=0;j--)
if(i.second>>j&1)
swap(cnt[j][1],cnt[j][0]);
}
}
signed main()
{
n=read();
for(int i=1;i<60;i=-~i) mi[i]=(mi[i-1]<<1)%mod;
for(int i=1,u,v,w;i<n;i=-~i)
u=read(),v=read(),w=read(),
e[u].push_back({v,w}),e[v].push_back({u,w});
dfs1(1,0,0);dfs2(1,0);
return printf("%lld",ans*500000004/*显然这是2在mod 1e9+7下的逆元*/%mod),0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】