题目链接:E. Bitwise Queries
题意
这是一道交互题,分为两个版本 Easy 和 Hard 两者只在询问次数上不同。
给出一个长度为 n 的非负整数序列 a1,a2,⋯,an,并保证 ai∈[0,n−1] 和 n=2t,你可以进行一下三种询问操作:
-
AND i j
:表示询问 ai&aj(“与”操作)
-
OR i j
:表示询问 ai∣aj(“或”操作)
-
XOR i j
:表示询问 ai⊕aj(“异或”操作)
通过若干次询问,求出该序列。
本题分为两种难度 Easy 版允许询问 n+2 次, Hard 版允许询问 n+1 次。
数据范围:n=2t,2⩽t⩽16。
思路
有关位运算的恒等式请见 与位运算有关的恒等式,下文中的恒等式出自于此。
Easy版本
核心是使用恒等式:a+b=(a⊕b)+2(a&b)。
先通过 n−1 次询问,求出 a1⊕a2,a1⊕a3,⋯,a1⊕an,然后再通过3次询问,求出 a1&a2,a1&a3,a2&a3,一共 n+2 次询问。
通过后三次询问和上面的恒等式,求出 a+b,b+c,a+c,进一步 a=2(a+b)+(a+c)−(b+c),于是可以求出 a1,再通过异或运算求出其他所有元素。
时间复杂度 O(n)。
点击显/隐代码
Hard版本
第一步还是先通过 n−1 次询问,求出来 a1⊕a2,a1⊕a3,⋯,a1⊕an。
可以发现,easy版本连 n=2t 和 ai∈[0,n−1] 这俩条件都没有使用过。
于是我们通过分类思想来想如何使用第二个条件:
-
如果存在 aj=ak,则 a1⊕aj=a1⊕ak,于是 aj&ak=aj=ak,所以可以通过1次询问求出来 aj,于是通过异或我们又可以求出来 a1,进一步求出其他所有数,总询问次数 n−1+1=n 次。
-
如果不存在 aj=ak,则 a1∼an 一定是均与分布在 [0,n−1] 中,且两两不同,这时第一个条件就起作用了,那么一定存在 a1+aj=n−1=2k−1,再细想 2k−1 是什么,它的二进制全部是1,于是 a1 和 aj 的二进制数位一定是错开的,也就是 a1&aj=0,这不就正好凑成了 easy 版本的一个与条件么,于是在找到第三个值 ak,通过询问两次 a1&ak,aj&ak 即可求出 a1 了!总询问次数 n−1+2=n+1。
第一种情况的 a1⊕aj=a1⊕ak 可以通过 map
查找得到,时间复杂度 O(nlogn)。
点击显/隐代码