CF1451E - Codeforces Round 685 (Div. 2) E. Bitwise Queries

题目链接:E. Bitwise Queries

题意

这是一道交互题,分为两个版本 Easy 和 Hard 两者只在询问次数上不同。

给出一个长度为 nn 的非负整数序列 a1,a2,,ana_1, a_2, \cdots, a_n,并保证 ai[0,n1]a_i \in [0, n-1]n=2tn=2^t,你可以进行一下三种询问操作:

  • AND i j:表示询问 ai&aja_i \& a_j(“与”操作)

  • OR i j:表示询问 aiaja_i | a_j(“或”操作)

  • XOR i j:表示询问 aiaja_i \oplus a_j(“异或”操作)

通过若干次询问,求出该序列。

本题分为两种难度 Easy 版允许询问 n+2n+2 次, Hard 版允许询问 n+1n+1 次。

数据范围:n=2t,2t16n = 2^t, 2\leqslant t \leqslant 16

思路

有关位运算的恒等式请见 与位运算有关的恒等式,下文中的恒等式出自于此。

Easy版本

核心是使用恒等式:a+b=(ab)+2(a&b)a+b=(a\oplus b) + 2(a\& b)

先通过 n1n-1 次询问,求出 a1a2,a1a3,,a1ana_1\oplus a_2, a_1\oplus a_3, \cdots, a_1\oplus a_n,然后再通过3次询问,求出 a1&a2,a1&a3,a2&a3a_1\& a_2, a_1\& a_3, a_2\& a_3,一共 n+2n+2 次询问。

通过后三次询问和上面的恒等式,求出 a+b,b+c,a+ca+b, b+c, a+c,进一步 a=(a+b)+(a+c)(b+c)2a=\frac{(a+b)+(a+c)-(b+c)}{2},于是可以求出 a1a_1,再通过异或运算求出其他所有元素。

时间复杂度 O(n)O(n)

Hard版本

第一步还是先通过 n1n-1 次询问,求出来 a1a2,a1a3,,a1ana_1\oplus a_2, a_1\oplus a_3, \cdots, a_1\oplus a_n

可以发现,easy版本连 n=2tn=2^tai[0,n1]a_i\in[0,n-1] 这俩条件都没有使用过。

于是我们通过分类思想来想如何使用第二个条件:

  • 如果存在 aj=aka_j=a_k,则 a1aj=a1aka_1\oplus a_j=a_1\oplus a_k,于是 aj&ak=aj=aka_j\& a_k = a_j = a_k,所以可以通过1次询问求出来 aja_j,于是通过异或我们又可以求出来 a1a_1,进一步求出其他所有数,总询问次数 n1+1=nn-1+1=n 次。

  • 如果不存在 aj=aka_j=a_k,则 a1ana_1\sim a_n 一定是均与分布在 [0,n1][0, n-1] 中,且两两不同,这时第一个条件就起作用了,那么一定存在 a1+aj=n1=2k1a_1+a_j=n-1=2^k-1,再细想 2k12^k-1 是什么,它的二进制全部是1,于是 a1a_1aja_j 的二进制数位一定是错开的,也就是 a1&aj=0a_1 \& a_j = 0,这不就正好凑成了 easy 版本的一个与条件么,于是在找到第三个值 aka_k,通过询问两次 a1&ak,aj&aka_1 \& a_k, a_j\& a_k 即可求出 a1a_1 了!总询问次数 n1+2=n+1n-1+2=n+1

第一种情况的 a1aj=a1aka_1\oplus a_j=a_1\oplus a_k 可以通过 map 查找得到,时间复杂度 O(nlogn)O(n\log n)


CF1451E - Codeforces Round 685 (Div. 2) E. Bitwise Queries
https://wty-yy.github.io/posts/16773/
作者
wty
发布于
2021年9月3日
许可协议