所有对的异或值之和
Posted
技术标签:
【中文标题】所有对的异或值之和【英文标题】:sum of xor values of all pairs 【发布时间】:2014-02-18 17:44:53 【问题描述】:我们有一个数组 A (say [1,2,3])
。我们需要找到数组中所有整数对的XOR(^)SUM。
虽然这可以在O(n^2)
中轻松完成,但我怎样才能提高解决方案的复杂性?
例如,对于上面的数组 A,答案是 (1^2)+(1^3)+(2^3) = 6
谢谢。
【问题讨论】:
“总和”我假设你的意思是按位或。 没有。异或所有不同的对并计算所有这些值的总和。 在这种情况下我得到1^2+1^3+2^3 = 3 + 2 + 1 = 6
。
感谢马特..问题已更新。
[1,2,2]
的答案应该是什么?是(1^2)+(1^2)=6
,还是1^2=3
?如果是第一个,那么就没有必要在问题中指定“不同的对”,因为2^2=0
无论如何都不会影响总和。
【参考方案1】:
你可以分开计算,一次做一点。
例如,查看数组中所有数字的最右边的位。假设a
数字有一个最右边的 0 位,而b
数字有一个 1 位。然后在这些对中,a*b
在 XOR 的最右边位将有 1。这是因为有a*b
方法可以选择一个具有 0 位的数字和一个具有 1 位的数字。因此,这些位将对所有 XOR 的总数贡献a*b
。
一般来说,当查看n
th 位(其中最右边的位是第 0 位)时,计算有多少个数字有 0(称之为 an)以及有多少个有 1(称之为 bn)。对最终总和的贡献将是 an*bn*2n。您需要对每一位执行此操作,并将所有这些贡献加在一起。
这可以在 O(kn) 时间内完成,其中k
是给定值中的位数。
【讨论】:
好主意 Interjay!非常感谢:) 好主意。谢谢 这个条件对于数组 [2,3] 是如何成立的,2 和 3 的异或是 1,但结果是 1+2=3。 @RaviSevta 这将给出 1*11 + 2*0*2 = 1 这是正确的。 @RaviSevta 是 1*2*1 + 1*2*2 = 6。对于每个位位置,1 位和 0 位的数量之和必须为 3,因为有 3 个数字在列表中。【参考方案2】:这是一个jsFiddle 确认 interjay 的答案,它使用 O(N^2) 与 O(Nk) 两种方法进行计算:
var list = [1,2,2,3,4,5]
function xorsum_on2( a )
var sum = 0
for( var i=0 ; i<a.length ; ++i )
for( var j=i+1 ; j<a.length ; ++j )
sum += a[i]^a[j]
return sum
// This sets all elements of a to 0
function xorsum_onk( a )
var allzeroes;
var sum = 0;
var power = 0;
do
allzeroes = true;
var bitcount = [0,0];
for( var i=0 ; i<a.length ; ++i )
bitcount[a[i]&1]++;
a[i] >>= 1;
if( a[i] ) allzeroes = false;
sum += (bitcount[0]*bitcount[1]) << power++;
while( !allzeroes );
return sum;
var onk = document.getElementById("onk")
var on2 = document.getElementById("on2")
on2.innerhtml = xorsum_on2(list)
onk.innerHTML = xorsum_onk(list)
【讨论】:
【参考方案3】:#include <iostream>
using namespace std;
int main()
long long int n,i,j,k;
cin>>n; // number of elements in array
long long int arr[n],ans=0;
for(i=0;i<n;i++)
cin>>arr[i];
// iterate through all the bits
for(i=0;i<32;i++)
k=0; // k is the number of set bits in the array at ith psotion
for(j=0;j<n;j++)
if((arr[j] & (1<<i)))
k++;
/* there are k set bits and n-k unset bits.
therefore number of pairs with one set bit and one unset bit is kC1 and n-kC1
Every pair adds 2^i in the answer.
*/
ans+= (1<<i)*(k*(n-k));
cout<<ans<<endl;
return 0;
【讨论】:
(这个答案增加了什么?(如果 Matt's answer 包含按位方法,我认为它是边缘的。))以上是关于所有对的异或值之和的主要内容,如果未能解决你的问题,请参考以下文章