按位数组操作
bitwise array manipulation
给你一个包含N个正整数的数组A(1 <= A[i] <= 10^9)
令 F(i,j,k) = ( A[i] | A[j] ) & A[k]
|表示按位或 & 表示按位与
任务是确定 F(A,B,C) 在所有三元组 (A,B,C) 上的按位异或,使得 1<= A,B,C <=N
例如:
如果 N=2 且 A=[1,4]
三胞胎将是:
- F(1,1,1) = 1
- F(1,1,2) = 0
- F(1,2,1) = 1
- F(1,2,2) = 4
- F(2,1,1) = 1
- F(2,1,2) = 4
- F(2,2,1) = 0
- F(2,2,2) = 4
所有的按位异或 = 1^0^1^4^1^4^0^4 = 5
所以答案是 5.
再举一个例子:
如果 A=[14,9,19,18,17,11,12] 答案=16
如何解决这个问题或如何处理此类问题?
javascript 中的代码会有所帮助,但也欢迎使用其他语言。
这些问题可以通过对每一位单独考虑来解决。
对于每一位,令 n0 为该位设置为 0 的数组元素的数量,并令 n1 为该位设置为 1 的元素的数量。
然后很容易确定答案中是否设置了该位:
- 在
A[i]|A[j]
中设置位的 i,j
对数是 n1*n1 + n1*n0*2
- 在 F(i,j,k) 中设置该位的三元组数
i,j,k
则为 n1*(n1*n1 + n1*n0*2)
- 由于所有的 F 都被异或在一起,如果它被设置为奇数个三元组,即如果上述表达式的计算结果为奇数,结果将设置位。
此时,我们可以通过计算每个位的 1 和 0 来轻松解决问题,但请注意,当 n1
为奇数时,n1*(n1*n1 + n1*n0*2)
计算为奇数,即,当该位在数组中出现奇数次时。如果在数组中设置了奇数次,则要获取每个位设置的数字...
只需将所有数组元素异或在一起。
@Matt 的第一个解决方案非常好。这是另一个使用简单数学技巧的解决方案。
下面异或用和表示法,&
用乘积表示法。
问题是计算F = sum F(i, j, k) = sum_{i, j, k} (A[i]|A[j]).A[k]
.
通过使用乘法 (&
) 对加法 (xor) 的分配 属性,我们得到:
F = sum_k A[k] . sum_{i, j} (A[i] | A[j])
我们注意到
A[i] | A[j] = A[i] + A[j] + A[i].A[j]
然后
sum_{i, j} (A[i] | A[j]) = sum_{i, j} (A[i] + A[j] + A[i].A[j])
如A + A = 0
,显然sum_{i, j} (A[i] + A[j] = 0
此外,if (i != j), A[i].A[j] + A[j].A[i] = 0
。因此,
sum_{i, j} A[i].A[j] = sum_i A[i].A[i] = sum_i A[i]
我们这里用的是A & A = A
.
最后,
F = sum_k A[k] . sum_k A[k] = sum_k A[k]
解决方法是对数组中的所有元素进行异或。
给你一个包含N个正整数的数组A(1 <= A[i] <= 10^9)
令 F(i,j,k) = ( A[i] | A[j] ) & A[k]
|表示按位或 & 表示按位与
任务是确定 F(A,B,C) 在所有三元组 (A,B,C) 上的按位异或,使得 1<= A,B,C <=N
例如:
如果 N=2 且 A=[1,4]
三胞胎将是:
- F(1,1,1) = 1
- F(1,1,2) = 0
- F(1,2,1) = 1
- F(1,2,2) = 4
- F(2,1,1) = 1
- F(2,1,2) = 4
- F(2,2,1) = 0
- F(2,2,2) = 4
所有的按位异或 = 1^0^1^4^1^4^0^4 = 5
所以答案是 5.
再举一个例子:
如果 A=[14,9,19,18,17,11,12] 答案=16
如何解决这个问题或如何处理此类问题?
javascript 中的代码会有所帮助,但也欢迎使用其他语言。
这些问题可以通过对每一位单独考虑来解决。
对于每一位,令 n0 为该位设置为 0 的数组元素的数量,并令 n1 为该位设置为 1 的元素的数量。
然后很容易确定答案中是否设置了该位:
- 在
A[i]|A[j]
中设置位的i,j
对数是n1*n1 + n1*n0*2
- 在 F(i,j,k) 中设置该位的三元组数
i,j,k
则为n1*(n1*n1 + n1*n0*2)
- 由于所有的 F 都被异或在一起,如果它被设置为奇数个三元组,即如果上述表达式的计算结果为奇数,结果将设置位。
此时,我们可以通过计算每个位的 1 和 0 来轻松解决问题,但请注意,当 n1
为奇数时,n1*(n1*n1 + n1*n0*2)
计算为奇数,即,当该位在数组中出现奇数次时。如果在数组中设置了奇数次,则要获取每个位设置的数字...
只需将所有数组元素异或在一起。
@Matt 的第一个解决方案非常好。这是另一个使用简单数学技巧的解决方案。
下面异或用和表示法,&
用乘积表示法。
问题是计算F = sum F(i, j, k) = sum_{i, j, k} (A[i]|A[j]).A[k]
.
通过使用乘法 (&
) 对加法 (xor) 的分配 属性,我们得到:
F = sum_k A[k] . sum_{i, j} (A[i] | A[j])
我们注意到
A[i] | A[j] = A[i] + A[j] + A[i].A[j]
然后
sum_{i, j} (A[i] | A[j]) = sum_{i, j} (A[i] + A[j] + A[i].A[j])
如A + A = 0
,显然sum_{i, j} (A[i] + A[j] = 0
此外,if (i != j), A[i].A[j] + A[j].A[i] = 0
。因此,
sum_{i, j} A[i].A[j] = sum_i A[i].A[i] = sum_i A[i]
我们这里用的是A & A = A
.
最后,
F = sum_k A[k] . sum_k A[k] = sum_k A[k]
解决方法是对数组中的所有元素进行异或。