# 982. Triples with Bitwise AND Equal To Zero

**<font color=red>难度: Hard</font>**

## 刷题内容

> 原题连接

* https://leetcode.com/problems/triples-with-bitwise-and-equal-to-zero/

> 内容描述

```
Given an array of integers A, find the number of triples of indices (i, j, k) such that:

0 <= i < A.length
0 <= j < A.length
0 <= k < A.length
A[i] & A[j] & A[k] == 0, where & represents the bitwise-AND operator.
 

Example 1:

Input: [2,1,3]
Output: 12
Explanation: We could choose the following i, j, k triples:
(i=0, j=0, k=1) : 2 & 2 & 1
(i=0, j=1, k=0) : 2 & 1 & 2
(i=0, j=1, k=1) : 2 & 1 & 1
(i=0, j=1, k=2) : 2 & 1 & 3
(i=0, j=2, k=1) : 2 & 3 & 1
(i=1, j=0, k=0) : 1 & 2 & 2
(i=1, j=0, k=1) : 1 & 2 & 1
(i=1, j=0, k=2) : 1 & 2 & 3
(i=1, j=1, k=0) : 1 & 1 & 2
(i=1, j=2, k=0) : 1 & 3 & 2
(i=2, j=0, k=1) : 3 & 2 & 1
(i=2, j=1, k=0) : 3 & 1 & 2
 

Note:

1 <= A.length <= 1000
0 <= A[i] < 2^16
```

## 解题方案

> 思路 1
******- 时间复杂度: O(N^3)******- 空间复杂度: O(1)******



开始试了一下暴力O(N^3)，超时


```
class Solution:
    def countTriplets(self, A: 'List[int]') -> 'int':
        res = 0
        for i in range(len(A)):
            for j in range(len(A)):
                for k in range(len(A)):
                    if A[i] & A[j] & A[k] == 0:
                        res += 1
        return res
```

做了一点优化，还是超时


```
class Solution:
    def countTriplets(self, A: 'List[int]') -> 'int':
        res = 0
        for i in range(len(A)):
            for j in range(i, len(A)):
                tmp = A[i] & A[j]
                for k in range(j, len(A)):
                    if tmp & A[k] == 0:
                        if i == j == k:
                            res += 1
                        elif i == j or j == k or k == i:
                            res += 3
                        else:
                            res += 6
        return res
```





> 思路 2
******- 时间复杂度: O(N^3)******- 空间复杂度: O(1)******


记忆化搜索，也超时

参考[C++ 20行题解，56ms，记忆化枚举](https://leetcode.com/problems/triples-with-bitwise-and-equal-to-zero/discuss/226778/C%2B%2B-2056ms)

1. 首先枚举 i 和 j，同时使用一个数组 f 记录 A[i] & A[j] 的值所对应的答案个数，即有多少个数字能使得 A[i] & A[j] & x == 0。
2. 枚举时，如果对应的 A[i] & A[j] 还没有记录，则暴力枚举 k，求出后将其添加到 f 中。如果有记录，则不再枚举，直接使用这个记录的值。

```
class Solution:
    def countTriplets(self, A: 'List[int]') -> 'int':
        n = len(A)
        res = 0
        cache = [-1] * (1 << 16)
        for i in range(n):
            for j in range(n):
                x = A[i] & A[j]
                if cache[x] == -1:
                    cache[x] = 0
                    for k in range(n):
                        if x & A[k] == 0:
                            cache[x] += 1
                res += cache[x]
        return res
```



> 思路 3
******- 时间复杂度: O(N^3)******- 空间复杂度: O(N^2)******


想到用counter，然后先确定一下A中每一对元素的AND的结果一共有多少种，每种各自有多少个，然后重新遍历我们的A，对于每一个元素a
看看count里面有哪一个AND结果and_res和a的AND为0，加上这个and_res的频率即可

worst case 如下：
```
maybe each pair of elements in original A will have a different AND result, 
therefore, the count can have O(N^2) elements in the worst case.
```

空间最差为O(N^2)


```python
class Solution:
    def countTriplets(self, A: 'List[int]') -> 'int':
        res = 0
        count = collections.Counter()
        for i in range(len(A)):
            for j in range(len(A)):
                count[A[i]&A[j]] += 1
        for k in range(len(A)):
            for v in count:
                if A[k] & v == 0:
                    res += count[v]
        return res
```
























