link
AT5140 [AGC035C] Skolem XOR Tree
给定一个正整数 \(N\)
试判断,是否存在这样一棵节点数为 \(2N\) 的树,满足:
-
\(∀i∈[1,n]\),第 \(i\) 号节点和第 \(i+n\) 号节点的权值均为 \(i\)
-
第 \(i\) 号节点到第 \(i+N\) 号节点路径上的点的点权异或和恰为 \(i\)
sol
试考虑异或的性质 : $0 ⨁x=x $
也就是说,对于一对 \(i,n+i\) 要构造出,除了 \(i\) 以外一直到 \(n+i\) 的异或和为 \(0\) (包括 \(n+i\))
所以考虑 \(2n+1⨁2n=1\) 这个答案再异或上 \(1\)就是 \(0\) 了
所以我们可以讲 \(i\)和 \(i+1\) 看成一对来处理,一对 \(i,i+1,2n+i,2n+i+1\) 我们可以这样连
\(i+1--i --1--2n+i+1--2n+i\)
这样成对就可以满足了
然后考虑 \(1\) 怎么连,我们发现 \(1⨁2⨁3=0\),所以利用前面的性质
$1--2--3--n+1--n+2--n+3$6
如果 \(n\) 是偶数的话,上面的情况 \(n\)和 \(2n\) 是无法处理的
那么我们就要找一条经过 \(1\) 的路径 ,满足 \(x⨁y⨁1=n\) 那么将 \(n\) 连 \(x\) 连 \(1\) 连 \(y\) 连 \(2n\) 就满足了,但是注意不能选 \(3\) ,因为 \(3\) 不是和 \(1\) 直接相连的
通过观察样例我们发现,如果 \(n\) 是 \(2\) 的整数次幂无解,因为只有 \(n\) 的最高位是 \(1\) ,比 \(n\) 小的数不可能将最高位构造出 \(1\)
code
#include<bits/stdc++.h>
using namespace std;
int n,m;
int main(){
freopen("AT5140.in","r",stdin);
freopen("AT5140.out","w",stdout);
scanf("%d",&n);m=log2(n);
if(!((1<<m)^n))return printf("No\n"),0;
printf("Yes\n");
printf("%d %d\n",1,2);
printf("%d %d\n",2,3);
printf("%d %d\n",3,n+1);
printf("%d %d\n",n+1,n+2);
printf("%d %d\n",n+2,n+3);
for(int i=2;2*i+1<=n;i++){
printf("%d %d\n",1,2*i);
printf("%d %d\n",1,2*i+1);
printf("%d %d\n",2*i,2*i+n+1);
printf("%d %d\n",2*i+1,2*i+n);
}
if(!(n&1)){
for(int i=2;i<=n;i++){
if(i==3) continue;
int y=(i^1^n);
if(y==3||y>n) continue;
printf("%d %d\n",n,i);
printf("%d %d\n",2*n,y);
break;
}
}
return 0;
}