xor

8 篇文章 0 订阅

#include <iostream>


int main()

{

    int n;

    while (scanf("%d",&n)!=EOF) {

        __int64 i,j,a[100010],sum1[21],ans=0;

        memset(a, 0, sizeof(a));

        memset(sum1, 0, sizeof(sum1));

        for (i=0; i<n; i++) {

            scanf("%I64d",&a[i]);

            for (j=0; a[i]; j++,a[i]/=2)

                if (a[i]%2)

                    sum1[j]++;

        }

        for (i=0; i<20; i++)

            ans+=sum1[i]*(n-sum1[i])*(2<<i);//(2<<i)==2*pow(2,i);

        printf("%I64d\n",ans);

    }

    return 0;

}

/*

虽然题意很简单,但是数据可不简单,n达到了100000。如果直接求的话,最多需要100000^2次运算,

 无论如何都不能在规定的时限内出解,所以我们就要想想别的方法。考虑到位运算是针对每一个二进制位来的,

 那么,我们就将每一个二进制位单独处理。首先将所有的数转化成二进制数,

 然后将每一个二进制位上的01个数统计出来。由于只有当0 xor 1时能得出1

 那么假设2^i这一位上有a0b1,那么一共会有a*b*2次运算这一位为1

 也就是最后的答案包含a*b*22^i。如此一来我们最多只要用20次计算就可以得出最后的答案。

 而一开始的预处理需要nlogn的复杂度。所以总的时间复杂度是Onlogn)。

*/

/*

 Problem description

 We all know that huicpc302 is good at maths, now he does a job below.

 

 At first he got a n numbers.

 

 Then he got a function below:

 long long Cal(int a[], int n)

 {

 int i, j;

 long long ret = 0;

 for(i = 0; i < n; i ++)

 {

 for(j = 0; j < n; j ++)

 {

 ret += a[i]^a[j];

 }

 }

 return ret;

 }

 Now he wants to know what he will get, when using the function to the calculate the n numbers.

 Note that when n is too large, this function works slowly, but huicpc302 wants to get the answer as soon as possible.

 

 

 Input

 There are several test cases in the input, the first line of each test case is an integer n, the second line contains n(1 <= n <= 100000) integers, a0, a1, a2... an-1. (1 <= ai < 219). The input ends by EOF.

 

 Output

 For each test case, output one line, the result.

 

 Sample Input

 5

 41 18467 6334 26500 19169

 5

 15724 11478 29358 26962 24464

 Sample Output

 338484

 352232

*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值