题解 P3727 【曼哈顿计划E】

· · 题解

一句话题意:

一颗树上每个点有权值(SG函数值),问能否选择一条链,使SG函数值异或和为零。

预备知识

不会SG函数的同学请移步这里 -> ydc老师的博客

题解

直接放神犇同学@loveyayoi的题解:

n

k

- k=4时,打表得知,
$$sg(x)=
\begin{cases}
0 & \text{ , } x= 0 \\
x & \text{ , } x\equiv 1,2 (mod\ 4) \\
x+1 & \text{ , } x\equiv 3 (mod\ 4) \\
x-1 & \text{ , } x\equiv 0 (mod\ 4)
\end{cases}
## w - w<=1000,暴力筛出sg函数即可 - w<=1e9,找规律O(1)求sg函数 ## 复杂度 $O(T N log N)$,假设hash达到期望复杂度$O(1)$ 代码: ```cpp #include <bits/stdc++.h> using namespace std; const int MAXN=30005, MAXB=1e7; char BUF[MAXB], *cp=BUF; void rd(int &x){ x=0; while(*cp<'0'||'9'<*cp) cp++; while('0'<=*cp&&*cp<='9') x=x*10+*cp-'0', cp++; } int ne, hs, ok, nt, T, N, K, S; int w[MAXN], sz[MAXN], vis[MAXN], tp[MAXN]; struct Edge{Edge *nxt; int to;}E[MAXN<<1], *hd[MAXN]; void adde(int u, int v){ E[ne].to=v; E[ne].nxt=hd[u]; hd[u]=&E[ne++]; E[ne].to=u; E[ne].nxt=hd[v]; hd[v]=&E[ne++]; } int sg1(int x){return x;} int sg2(int x){return (x+1)%(S+1)?x&1:2;} int sg3(int x){return x/S;} int sg4(int x){ switch(x%4){ case 0: return x-1; case 3: return x+1; default: return x; } } void init(){ memset(hd,0,sizeof(hd)); ne=0; memset(vis,0,sizeof(vis)); } int gs(int u, int p){ sz[u]=1; for(Edge *e=hd[u]; e; e=e->nxt){ int v=e->to; if(v!=p&&!vis[v]) sz[u]+=gs(v,u); } return sz[u]; } int gg(int u, int p){ for(Edge *e=hd[u]; e; e=e->nxt){ int v=e->to; if(v!=p&&!vis[v]&&sz[v]>=hs) return gg(v,u); } return u; } int tt[MAXN]; void dfs(int u, int p, int s){ tt[nt]=u;tp[nt++]=s; for(Edge *e=hd[u]; e; e=e->nxt){ int v=e->to; if(v!=p&&!vis[v]) dfs(v,u,s^w[v]); } } struct Hash{ static const int P1=100003, P2=100069; inline int h1(int x){return x%P1;} inline int h2(int x){return x%P2;} int t1[P1], t2[P2], st[MAXN], top; Hash(){ memset(t1,-1,sizeof(t1)); memset(t2,-1,sizeof(t2)); } int find(int x){return t1[h1(x)]==x||t2[h2(x)]==x;} void insert(int x){ if(find(x)) return; int h=h2(x); st[top++]=x; if(t2[h]==-1) t2[h]=x; else while(~x){ h=h1(x); swap(x,t1[h]); if(x==-1) return; h=h2(x); swap(x,t2[h]); } } void del(int x){ if(t1[h1(x)]==x) t1[h1(x)]=-1; else t2[h2(x)]=-1; } void clear(){ while(top) del(st[--top]);} }H; void dc(int u){ hs=gs(u,0)>>1; int g=gg(u,0); vis[g]=1; H.insert(0); for(Edge *e=hd[g]; e; e=e->nxt){ int v=e->to; if(!vis[v]){ nt=0; dfs(v,0,w[v]); for(int i=0; i<nt; ++i){ if(H.find(w[g]^tp[i])){ok=1;break;} } for(int i=0; i<nt; ++i) H.insert(tp[i]); } } H.clear(); for(Edge *e=hd[g]; e&&!ok; e=e->nxt) if(!vis[e->to]) dc(e->to); } int main(){ fread(BUF, 1, MAXB, stdin); rd(T); while(T--){ init(); rd(N); for(int i=1,u,v; i<N; ++i) rd(u),rd(v),adde(u,v); for(int i=1; i<=N; ++i) rd(w[i]); rd(K); int (*sg)(int); if(K==1) sg=sg1; else if(K==2) rd(S),sg=sg2; else if(K==3) rd(S),sg=sg3; else sg=sg4; ok=0; for(int i=1; i<=N; ++i) if(!(w[i]=sg(w[i]))) ok=1; if(!ok) dc(1); puts(ok?"Mutalisk ride face how to lose?":"The commentary cannot go on!"); } return 0; } ```