性质
1.
百度百科给的
最主要的性质就是归零和结合,其他的就都是拓展了。
例题:P1469
2.
\(a \bigoplus b<=a+b\)
关于这个不等式比较好的理解为异或就是不进位的加法
例题:luoguP5514
应用
异或哈希
异或跟hash一样,也是会发生冲突的
例如:$1 \bigoplus 2 = 5 \bigoplus 6 $
那我们要怎么去避免冲突呢,我们就可以借助hash的思想,对异或值做一个映射,或基于一个base来达成。
来看这道题,我们先来分析Crying的必胜策略:
假设Crying首先拿最小的数,如果最小的数有奇数个,那Crying会赢,如果为偶数个,那Crying肯定不会上来就拿最小的数,而是先去考虑拿第二小的数,那同样如果第二小的数为奇数个,Crying胜,如果为偶数个,那就接着考虑第三小的数,以此类推……
那转化一下题意就是求保证路径上每个数字不会出现偶数次的路径,再转化一下那这就是要保证路径的异或和不为 \(0\) (异或的归零性质,相同的数两两相抵消)。
但是,这样就会出现一个问题:异或冲突
我们就可以用上面的方法来避免这个问题,那这题就好办了,我们加边的时候给边权乘一个base,然后dfs跑一遍每个点到根节点的异或和,最后统计一下。这个时间限制不支持\(O(n^2)\)的操作,我们就可以开个map存一下dis相同的个数,最后减去即可。
点击查看代码
#include<bits/stdc++.h>
using namespace std;#define int long long
const int N=5e6+107;
int n;int read()
{int f=1,s=0;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}return f*s;
}unsigned long long qpow(unsigned long long a,int b)
{unsigned long long ans=1;while(b){if(b&1) ans=ans*a;a=a*a;b=b>>1;}return ans;
}int h[N],to[N],nxt[N],w[N],tot;
void add(int x,int y,int dt)
{to[++tot]=y;nxt[tot]=h[x];w[tot]=dt;h[x]=tot;
}
unordered_map<int,int>mp,vis;int dis[N];
void dfs(int u,int fa)
{for(int i=h[u];i;i=nxt[i]){int v=to[i];if(v==fa) continue;dis[v]=dis[u]^w[i];dfs(v,u);}mp[dis[u]]++;
}void clear()
{memset(h,0,sizeof h);mp.clear(); vis.clear();tot=0;
}signed main()
{int T=read();while(T--){clear();n=read();for(int i=1;i<=n-1;i++){int x=read(),y=read(),dt=qpow(237,read()+1);add(x,y,dt); add(y,x,dt);}dfs(1,0);int ans=n*(n-1)/2;for(int i=1;i<=n;i++){if(vis[dis[i]]) continue;ans-=mp[dis[i]]*(mp[dis[i]]-1)/2;vis[dis[i]]=1;}printf("%lld\n",ans);}
}