XOR and (bit operation)

Time limit: 1 Sec Memory limit: 128 MB

Title description
There is an array a with n elements, let f(i,j)=ai xor aj.

Now you ask for the sum of f(i,j) for all 1≤i≤j≤n.
Enter the
first line, a positive integer n.
The next n numbers represent ai.
The output
is only one line, a positive integer, representing the sum.
Sample input Copy

3
1 2 3

Sample output Copy

6

Tip
For 30% of the data, n≤3000.
For the other 20% of the data, ai≤1.
For 100% data, 1≤n≤2×10^5, 0≤ai≤10^5.
The meaning of the question is very simple, that is, to find the sum of the exclusive OR of n numbers.
The conventional solution is to use double loop enumeration:

for i=1...n
	for j=i...n
		sum<-sum+a(i)^a(j)
	end
end

The time complexity of this solution is O(n^2), and it is no longer applicable when the amount of data is too large.
Since the XOR operation is a bitwise XOR, you can start with binary. It can be seen from the nature of the XOR operation that when two numbers are different, the XOR result is 1, and the final XOR sum is only related to the position where the XOR result is 1. Therefore, it is only necessary to count all the numbers on a certain place The result of the pairwise XOR is the number of 1, and then multiply the number by the weight of the current bit, and add it to get the answer. So how do you count the number of pairs where the result of XOR is 1? Recalling the nature of the XOR operation, set the number of bits 0 and 1 as x and y respectively, then x*y is the result to be counted.
for example:

input:
4
2 3 5 8
转化为二进制:
2=>0 0 1 0
3=>0 0 1 1
5=>0 1 0 1
8=>1 0 0 0
ans[]的值为:1 1 2 2
从每一位来看,所有(0,1)对的个数就是两两异或的结果为1的个数。
(0,1)对的个数:3(=3(0的个数)*1(1的个数)) 3(=3(0的个数)*1(1的个数)) 4(=2(0的个数)*2(1的个数)) 4(=2(0的个数)*2(1的个数))
权值:2^3 2^2 2^1 2^0
异或和=3*2^3+3*2^2+4*2^1+4*2^0=48

Note that the size of the array a[] can hold at least the largest binary number in the range (100000, 17 bits).

#include<cstdio>
#include<algorithm>
using namespace std;
int ans[20]={
    
    0};//log2(100000)约为17,这里的数组大小应该开到至少20
long long int res=0;
int main()
{
    
    
    int n,a,i,len,mmax=-1;//mmax表示所有数中最大的二进制位数
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
    
    
        scanf("%d",&a);
        len=0;
        while(a)
        {
    
    
            len++;
            if(a&1)ans[len]++;//记录当前位为1的个数
            a=a>>1;
        }
        mmax=max(mmax,len);
    }
    for(i=1;i<=mmax;i++)
    {
    
    
        res+=(long long int)(1<<(i-1))*(long long int)ans[i]*(long long int)(n-ans[i]);//强转为long long
    }
    printf("%lld",res);
    return 0;
}
/**************************************************************
    Language: C++
    Result: 正确
    Time:39 ms
    Memory:1120 kb
****************************************************************/

Guess you like

Origin blog.csdn.net/upc122/article/details/106535437