「yyOI R1」youyou 的异或 题解

· · 题解

这里是出题人题解。

Solution

5pts

随便手模两下即可算出 n \le 5 的情况,注意 n=3 无解即可得分。

15pts

可以通过各种奇奇怪怪的爆搜来通过 n \le 10 的数据。

40pts

给一些 O(n^2) 的算法通过的数据,但我没有想出来怎么用这个复杂度构造。

100pts

异或均用 \oplus 代替。

做本题前需要先明确几个比较简单的性质:a 是正整数)

这个性质很好理解:aa+1 只有最低位是不同的,所以异或以后为 1

明确了上述性质,我们很快会有一个想法:可以考虑将一个偶数与比该偶数多 1 的奇数视为一组,这样每一组的异或和为 1。而每两组的异或和为 0

即,当 a 是偶数时,a \oplus (a+1)=1a \oplus (a+1) \oplus (a+2)\oplus (a+3)=0

发现两组是 4 个数,根据 n \% 4 的余数进行分类讨论构造:

考虑构造序列 \{1,2,3,4,...,n\}。因为除 1n 以外,剩下的数为 4k + 2 个,为 2k+1 组,所以除 1n 以外的其他数异或和为 1 ,再有 1 \oplus 1\oplus n = n,所以构造成立。

例如 n = 8 时可以构造序列为 \{a\} = \{1,2,3,4,5,6,7,8\}

考虑构造序列 \{2,3...,n-2,n,n+1,n+2\},因为除 n 以外,剩下的数为 4k 个,可以分成 2k 组,所以异或和为 0,再有 0 \oplus n = n,所以构造成立。

例如 n = 9 时可以构造序列为 \{a\} = \{2,3,4,5,6,7,9,10,11\}

考虑构造序列 \{1,2,3,...,n-1,n+1\},因为除 1n + 1 以外,剩下的数为 4k 个,可以分成 2k 组,所以异或和为 0,再有 0 \oplus 1 \oplus n+1 = n,所以构造成立。

例如 n = 6 时可以构造序列为 \{a\} = \{1,2,3,4,5,7\}

例如 n = 7 时可以构造序列为 \{a\} = \{2,3,4,5,6,8,9\}

n 很小时需要注意不能按照上述方式构造,否则可能存在问题。

n = 3 时,通过手模可知没有构造方案满足要求,所以无解。

# Code ```cpp #include <bits/stdc++.h> using namespace std; int n, T; int main() { scanf("%d", &T); while(T--) { scanf("%d", &n); if(n == 1) { puts("1"); continue; } if(n == 3) { puts("-1"); continue; } if(n % 4 == 0) { for(int i = 1; i <= n; i++) { printf("%d ", i); } } else if(n % 4 == 1) { for(int i = 2; i < n - 1; i += 2) { printf("%d %d ", i, i + 1); } printf("%d %d %d ", n, n + 1, n + 2); } else if(n % 4 == 3) { for(int i = 2; i < n - 1; i += 2) { printf("%d %d ", i, i + 1); } printf("%d %d %d ", n - 1, n + 1, n + 2); } else { for(int i = 1; i <= n - 1; i++) { printf("%d ", i); } printf("%d ", n + 1); } puts(""); } return 0; } ```