所有对的异或值之和

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

一般来说,当查看nth 位(其中最右边的位是第 0 位)时,计算有多少个数字有 0(称之为 an)以及有多少个有 1(称之为 bn)。对最终总和的贡献将是 an*bn*2n。您需要对每一位执行此操作,并将所有这些贡献加在一起。

这可以在 O(kn) 时间内完成,其中k 是给定值中的位数。

【讨论】:

好主意 Interjay!非常感谢:) 好主意。谢谢 这个条件对于数组 [2,3] 是如何成立的,2 和 3 的异或是 1,但结果是 1+2=3。 @RaviSevta 这将给出 1*1​​1 + 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 包含按位方法,我认为它是边缘的。))

以上是关于所有对的异或值之和的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode﹝异或ி﹞解码异或区间查询第k大异或值

LeetCode﹝异或ி﹞解码异或区间查询第k大异或值

算法题2425. 所有数对的异或和

POJ3764 The xor-longest Path

[TJOI 2017]异或和

异或和(权值树状数组)