【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;
}
posted @ 2021-10-09 22:44  stoorz  阅读(37)  评论(0编辑  收藏  举报