【AtCoder Grand Contest 035 C】Skolem XOR Tree

构造

题目大意:

给定 $n$,要求构造 $2n$ 个结点的树,满足:

  • 对于 $1\leq i\leq n$,结点 $i$ 和 $i+n$ 的权值为 $i$。
  • 对于 $1\leq i\leq n$,结点 $i$ 到 $i+n$ 的简单路径上的所有点权的异或和为 $i$。

若没有可行方案则输出 No,否则给出方案。

题解:

当 $n=2^k$ 时,无解。因为二进制第 $k$ 位为 $1$ 的只有 $n$ 和 $2n$ 两个结点,这两个结点异或后为 $0$,中间的结点无论如何都无法得到最高位的 $1$。

考虑 $2n$ 和 $2n+1$ 的异或和为 $1$,所以构造这样的一条链 $(2n)-(2n+1)-1-(2n)-(2n+1)$ 满足条件。

由于是一棵树,我们可以取出一个 $1$ 共用。另外一个 $1$ 随便接到一条链尾部即可。

然后对于 $n$ 为奇数的情况就构造完毕了。

我们发现此时共用的 $1$ 旁边恰好有 $2\sim n$。这些结点,然后对于 $n$ 为偶数的情况,我们要找到 $2\sim n$ 中两个不同的数,其异或和为 $1$。显然存在解。

于是构造完毕。

Code:

#include<cstdio>
int n;
int main(){
    scanf("%d",&n);
    if(n==1<<(31-__builtin_clz(n)))return puts("No"),0;
    puts("Yes");
    printf("%d %d\n%d 3\n3 1\n1 2\n2 %d\n",1+n,2+n,2+n,3+n);
    for(int i=4;i+1<=n;i+=2)
    printf("%d %d\n%d 1\n1 %d\n%d %d\n",i+n,i+1,i+1,i,i,i+1+n);
    if(n%2==0){
        int x=__builtin_ctz(n);
        printf("%d %d\n%d %d\n",n,1<<x,n^1^(1<<x),2*n);
    }
    return 0;
}