【AGC035C】Skolem XOR Tree
阿新 • • 發佈:2021-10-09
題目
題目連結:https://atcoder.jp/contests/agc035/tasks/agc035_c
- 給定一個正整數 \(N\)。
- 試判斷,是否存在這樣一棵節點數為 \(2N\) 的樹,滿足:
- \(\forall i \in [1,n]\),第 \(i\) 號節點和第 \(i+n\) 號節點的權值均為 \(i\)。
- 第 \(i\) 號節點到第 \(i+N\) 號節點路徑上的點的點權異或和恰為 \(i\)。
- 若不存在這樣的樹,請輸出一行
No
。 - 否則先輸出一行
Yes
,然後再輸出 \(2N-1\) 行,每行兩個正整數 \(u,v\) 描述樹上的一條連線 \(u,v\) 的邊。 - \(1 \leq N \leq 10^5\)
思路
對於一個偶數 \(x\),有 \(x\text{ xor }(x+1)=1\)。考慮連邊 \((1,x),(1,x+1),(x,x+1+n),(x+1,x+n)\)。這樣從 \(x\) 到 \(x+n\) 的路徑,以及從 \(x+1\) 到 \(x+1+n\) 的路徑,都是符合要求的。
然後考慮點 \(1\) 應該如何匹配。觀察到 \(1\text{ xor }2\text{ xor }3=0\),所以可以連邊 \((1,2),(2,3),(3,1+n),(1+n,2+n),(2+n,3+n)\)。
然後當 \(n\) 是偶數時,無法像剛剛那樣利用 \(n+1\) 來進行匹配。那麼:
- 如果 \(n=2^k\),那麼除了 \(n\) 和 \(2n\) 以外,所有數在二進位制下第 \(k\) 位都為 \(0\),那麼一定無解。
- 如果 \(n\neq 2^k\),只需要找到一組 \(x,y\),滿足 \(x\text{ xor } y\text{ xor }1=n\),然後連邊 \((x,n),(y,2n)\) 即可。注意 \(x\) 和 \(y\) 都不能為 \(3\) 且必須小於 \(n\)。容易發現是一定存在這樣的 \(x,y\) 的。
程式碼
#include <bits/stdc++.h> using namespace std; int n; int main() { scanf("%d",&n); for (int i=0;i<=18;i++) if (n==(1<<i)) return printf("No"),0; printf("Yes\n1 2\n2 3\n3 %d\n%d %d\n%d %d\n",n+1,n+1,n+2,n+2,n+3); for (int i=4;i<n;i+=2) printf("1 %d\n1 %d\n%d %d\n%d %d\n",i,i+1,i,i+1+n,i+1,i+n); if (!(n&1)) for (int i=2;i<n;i++) if (i!=3 && (n^1^i)!=3 && (n^1^i)<n) return printf("%d %d\n%d %d\n",n,i,n*2,n^1^i),0; return 0; }