1. 程式人生 > 其它 >【AGC035C】Skolem XOR Tree

【AGC035C】Skolem XOR Tree

題目

題目連結: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;
}