📌  相关文章
📜  从给定的按位异或和按位与所有对的值中找到三元组(1)

📅  最后修改于: 2023-12-03 15:06:38.308000             🧑  作者: Mango

从给定的按位异或和按位与所有对的值中找到三元组

本文将介绍如何在给定的按位异或和按位与所有对的值中找到三元组。这个问题可以用一个简单的算法和数据结构来解决。

问题描述

给定一个长度为 $n$ 的整数数组 $a$。定义一个三元组 $(i, j, k)$ 是好三元组,当且仅当 $0\leq i<j<k\leq n-1$ 且

$$ a_i \operatorname{xor}a_j\operatorname{and}a_j\operatorname{xor}a_k \operatorname{and}a_i\operatorname{xor}a_k>0 $$

其中 $\operatorname{xor}$ 是按位异或运算,$\operatorname{and}$ 是按位与运算。

你可以找到 $a$ 中所有好三元组吗?

思路

注意到题目中的三个运算符是按位操作符,自然而然地,我们可以想到将每个数按二进制位分别处理。设 $a_{i, j}$ 表示 $a_i$ 在二进制下第 $j$ 位的值,也就是说

$$ a_i = \sum_{j=0}^{31} a_{i, j} \times 2^j $$

然后我们可以设 $s_1 = a_i \operatorname{xor}a_j$,$s_2= a_j \operatorname{xor}a_k$,$s_3 = a_i \operatorname{xor}a_k$。

注意到这三个数的每一位都是相互独立的。因此,我们可以针对所有可能的二进制位进行分类讨论,来得出这个三元组是否合法。更具体地说:

对于每一个二进制位 $j$:

如果 $s_{1,j} = s_{2,j} = 1$ 且 $s_{3,j}=0$,那么这个三元组是合法的,我们可以将这个三元组加入到答案中。

如果 $s_{1,j} = s_{2,j} = s_{3,j}=1$,那么这个三元组不合法,跳过。

如果 $s_{1,j} = s_{3,j} = 1$ 且 $s_{2,j}=0$,那么这个三元组不合法,跳过。

如果 $s_{1,j} = s_{2,j} = s_{3,j}=0$,那么这个二进制位已经无法对答案造成贡献了,直接跳过。

显然,对于所有的非空三元组,上述四种情况中恰好有一种成立,因此,我们可以把它们的计数交给一个计数器,最后将结果输出即可。

代码实现

下面是 Python 3 代码示例:

def count_triples(a: list) -> int:
    n, m = len(a), 32
    res = 0
    for j in range(m):
        cnt_0, cnt_1, cnt_2 = 0, 0, 0
        for i in range(n):
            if a[i] & (1 << j):
                if cnt_1 and cnt_2:
                    res += cnt_0 * cnt_1 * cnt_2
                cnt_2 += cnt_1
                cnt_1 += cnt_0
                cnt_0 = 0
            else:
                cnt_0 += 1
        if cnt_1 and cnt_2:
            res += cnt_0 * cnt_1 * cnt_2
    return res

上述代码的时间复杂度为 $O(n\log^2k)$,其中 $k$ 是数组中最大的数。虽然这个算法的时间复杂度比较高,但是还是可以在大多数机器上通过本题的。