0%

CF-1075-C2. XOR-convenience (Hard Version)(打表,错误的时候可以输出错误的地方)(如果说已经构造出来了简单版,复杂版可能也只需要微调)

题目大意

题目总结

问题描述

给定一个正整数 nn3n21053 \le n \le 2 \cdot 10^5)。你需要构造一个长度为 nn排列 pp(包含 11nn 的所有整数各一次),使得对于每一个 ii1in11 \le i \le n-1),都能在索引范围 [i,n][i, n] 中找到一个下标 jj(即 ijni \le j \le n),满足以下异或条件:

pi=pjip_i = p_j \oplus i

如果不存在满足条件的排列,则输出 1-1

输入输出

  • 输入:测试用例数量 tt,每个案例包含一个整数 nn

  • 输出:若存在,输出 nn 个整数表示排列 pp;否则输出 1-1


样例解释

n=3n=3 为例,输出为 2 1 3

  • i=1i=1 时:需要存在 j{1,2,3}j \in \{1, 2, 3\} 使得 p1=pj1p_1 = p_j \oplus 1
    已知 p1=2p_1=2,若取 j=3j=3,则 p31=31=2p_3 \oplus 1 = 3 \oplus 1 = 2。满足条件。

  • i=2i=2 时:需要存在 j{2,3}j \in \{2, 3\} 使得 p2=pj2p_2 = p_j \oplus 2
    已知 p2=1p_2=1,若取 j=3j=3,则 p32=32=1p_3 \oplus 2 = 3 \oplus 2 = 1。满足条件。

  • 所有 i[1,2]i \in [1, 2] 均满足条件,故 2 1 3 是合法解。

n=4n=4 为例:

  • 不存在任何长度为 44 的排列能满足上述所有约束,故输出 1-1

思路讲解

这道题目,一种方法是打表找规律,比较神秘,呃,也比较费时间,只不过由于我 C1 是打表打出来的,C2 也这样子尝试了,由于选取的规律比较奇怪,在某些情况下会出现问题,后需要与下标 lowbit(n)\text{lowbit}(n) 交换啊什么的,在这里就不介绍了。

不过可以总结一下,就是这种打表找规律的话,首先要确定没有答案的条件,其次就是写的检查器尽量报出更多的信息(在错误时),比如说这道题目,如果你构造出来的序列是错的,你写的检查器最好要报出来哪一位错了,有哪些位构造错误?这一位你填了什么值?反正信息越多越好。

那么构造方法如何解决 C1 呢?那么由于是要求 pi=pjip_i = p_j \oplus i,不妨就令 pi=i1p_i=i\oplus 1,把 1 放在最后就可以了,最后这样子生成的序列第一位可能有点问题,这个特判一下就行。

那么如果你会解决 C1 的话,其实只需要增加一行代码:

1
2
3
4
5
6
if (N%2==0) {
ans_ls[1]=N;
swap(ans_ls[1],ans_ls[lowbit(N)]);
}else {
ans_ls[1]=N-1;
}

swap(ans_ls[1],ans_ls[lowbit(N)]); 这一行代码。首先 lowbit(n)1\text{lowbit}(n)\oplus 1 肯定不愁找不到满足的 jj,因为他都处于第一个位置了。那么对于 nn 呢?那么由于 nnlowbit(n)lowbit(n)+2n≥n\oplus \text{lowbit}(n)≥\text{lowbit}(n)+2nn 是偶数),所以说也不用愁找不到 jj

当然,注意,nn 是 2 的幂次的时候是没有答案的,这也很容易理解,因为这个时候 nn 无论异或上 [1,n][1,n] 中的任何一个数字,其结果都超过了 [1,n][1,n] 的范围。

AC代码

AC
https://codeforces.com/contest/2189/submission/359568527

AC
https://codeforces.com/contest/2189/submission/359512601

心路历程(WA,TLE,MLE……)