介绍两种思路,一种被卡掉了
注意一下这个异或和是指 所有path(i,j)的异或
首先从一个根出发,算出跟到点x的路径异或为b[x]
那么对于两点的path(i,j)的答案即为:b[x]^b[y]^a[lca]
由于最终答案又是异或 也就是说path(i,j)表示为三个数异或然后在异或
显然对于每一个点而言,要异或其他n-1个点 ,也就是说该点在最终答案中b[i]出现次数是n-1次
所以首先看一下n的奇偶,如果为偶数首先把所有的b[i]异或起来
之后看一下a[u],a[u]就是作为lca异或的次数
通过dfs计算就可以了,判断奇偶性
Code:
/*** keep hungry and calm CoolGuang!***/ ///#pragma GCC optimize(3) #include <bits/stdc++.h> #define debug(x) cout<<#x<<":"<<x<<endl; using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pp; const ll INF=1e17; const int Maxn=1e6+10; const int maxn =2e6+10; const int mod= 1e9+7; const int Mod = 1e6+7; ///const double eps=1e-10; inline bool read(ll &num) {char in;bool IsN=false; in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;} ll n,m,p; struct node{ int e,next; }edge[maxn]; ll cnt = 0; int head[maxn]; void addedge(int u,int v){ edge[cnt] = node{v,head[u]}; head[u] = cnt++; } ll a[maxn],b[maxn]; void dfs(int u,int fa,ll w){ b[u] = a[u]^w; for(int i=head[u];~i;i=edge[i].next){ int e = edge[i].e; if(e == fa) continue; dfs(e,u,a[u]^w); } } ll sz[maxn]; ll ans = 0; void dfs(int u,int fa){ sz[u] = 1; ll res = 0; for(int i=head[u];~i;i=edge[i].next){ int e = edge[i].e; if(e == fa) continue; dfs(e,u); res += sz[u] * sz[e]; sz[u] += sz[e]; } if(res&1) ans ^= a[u]; } int main() { read(n); memset(head,-1,sizeof(head)); for(int i=1;i<=n-1;i++){ int x,y,z;scanf("%d%d",&x,&y); addedge(x,y); addedge(y,x); } for(int i=1;i<=n;i++) read(a[i]); dfs(1,1,0); dfs(1,1); ///debug(ans); if(!(n&1)) for(int i=1;i<=n;i++) ans^=b[i]; printf("%lld\n",ans); return 0; } /** 1000 **/
另外附带一个常数的做法:
这种问题我首先想到的是按位拆开
但是可能这个题把这个常数给卡掉了..
复杂度:32*n
/*** keep hungry and calm CoolGuang!***/ ///#pragma GCC optimize(3) #include <bits/stdc++.h> #define debug(x) cout<<#x<<":"<<x<<endl; #include<stdio.h> #include<algorithm> #include<queue> #include<string> #include<iostream> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pp; const ll INF=1e17; const int Maxn=1e6+10; const int maxn =2e6+10; const int mod= 1e9+7; const int Mod = 1e6+7; ///const double eps=1e-10; inline bool read(ll &num) {char in;bool IsN=false; in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;} ll n,m,p; struct node{ int e,next; }edge[maxn]; ll cnt = 0; int head[maxn]; void addedge(int u,int v){ edge[cnt] = node{v,head[u]}; head[u] = cnt++; } ll a[maxn],b[maxn]; void dfs(int u,int fa,ll w){ b[u] = a[u]^w; for(int i=head[u];~i;i=edge[i].next){ int e = edge[i].e; if(e == fa) continue; dfs(e,u,a[u]^w); } } ll sz[maxn][2]; ll res[105]; void TraceBack(int u,int fa,int bit){ int op = (b[u]>>bit&1)?1:0; sz[u][op] = 1; sz[u][!op] = 0; int opt = (a[u]>>bit&1)?1:0; for(int i=head[u];~i;i=edge[i].next){ int e = edge[i].e; if(e == fa) continue; TraceBack(e,u,bit); if(!opt) res[bit] += sz[e][0]*sz[u][1]+sz[e][1]*sz[u][0]; else res[bit] += sz[e][0]*sz[u][0]+sz[e][1]*sz[u][1]; sz[u][0] += sz[e][0]; sz[u][1] += sz[e][1]; } } int main() { read(n); memset(head,-1,sizeof(head)); for(int i=1;i<=n-1;i++){ int x,y,z;scanf("%d%d",&x,&y); addedge(x,y); addedge(y,x); } for(int i=1;i<=n;i++) read(a[i]); dfs(1,1,0); for(int i=0;i<=31;i++) TraceBack(1,1,i); ll ans = 0; for(int i=0;i<=31;i++) if(res[i]&1) ans |= 1ll<<i; printf("%lld\n",ans); return 0; } /** 1000 **/