Codeforces-1323D

D. Present

Catherine received an array of integers as a gift for March 8. Eventually she grew bored with it, and she started calculated various useless characteristics for it. She succeeded to do it for each one she came up with. But when she came up with another one — xor of all pairwise sums of elements in the array, she realized that she couldn’t compute it for a very large array, thus she asked for your help. Can you do it? Formally, you need to compute

(a1+a2)⊕(a1+a3)⊕…⊕(a1+an)⊕(a2+a3)⊕…⊕(a2+an)…⊕(an−1+an)
Here x⊕y is a bitwise XOR operation (i.e. x ^ y in many modern programming languages). You can read about it in Wikipedia: https://en.wikipedia.org/wiki/Exclusive_or#Bitwise_operation.

Input
The first line contains a single integer n (2≤n≤400000) — the number of integers in the array.

The second line contains integers a1,a2,…,an (1≤ai≤107).

Output
Print a single integer — xor of all pairwise sums of integers in the given array.

Examples
inputCopy
2
1 2
outputCopy
3
inputCopy
3
1 2 3
outputCopy
2
Note
In the first sample case there is only one sum 1+2=3.

In the second sample case there are three sums: 1+2=3, 1+3=4, 2+3=5. In binary they are represented as 0112⊕1002⊕1012=0102, thus the answer is 2.
⊕ is the bitwise xor operation. To define x⊕y, consider binary representations of integers x and y. We put the i-th bit of the result to be 1 when exactly one of the i-th bits of x and y is 1. Otherwise, the i-th bit of the result is put to be 0. For example, 01012⊕00112=01102.
题意:
给定一个序列,求出(a1+a2)⊕(a1+a3)⊕…⊕(a1+an)⊕(a2+a3)⊕…⊕(a2+an)…⊕(an−1+an)的结果。
比赛的时候想了一会,然后直接就放弃了。
赛后直接看大佬代码,有用树状数组做的,但是没看懂(tcl),今天搜到了大佬的博客,弄懂了。
逐位考虑答案即可,异或的性质,异或两次同一个数,结果不变(异或两次同一个数相当于不异或),所以,当结果的第K位为1时,就有奇数个(ai+aj)的第K位位1,高于第K位的数无影响,所以需要取余(取余保证第K位为1),取余过后,ai的取值范围就是[ 0 , 2^(k+1)-1], 所以(ai+aj)的取值范围就是[2k,2{k+1}-1]\cup [2{k+1}+2k,2^{k+2}-2] ,保证(ai+aj)的第K位为1,确定好ai,然后aj的范围就是[2k-a[i],2{k+1}-1-a[i]]\cup [2{k+1}+2k-a[i],2^{k+2}-2-a[i]] ,只需二分查找存在多少个数处于这个范围内即可。

#include<bits/stdc++.h>
using namespace std;
int a[400500];
int main() {
	int n;
	scanf("%d",&n);
	for(int i=1; i<=n; ++i) {
		scanf("%d",&a[i]);
	}
	int ans=0;
	for(int i=27; i>=0; --i) {
		for(int j=1; j<=n; ++j) {
			a[j]&=(1<<i+1)-1;
		}
		sort(a+1,a+n+1);
		for(int j=1; j<=n; ++j) {
			if((upper_bound(a+1,a+j,(1<<i+1)-1-a[j])-lower_bound(a+1,a+j,(1<<i)-a[j]))&1)ans^=(1<<i);
			if((upper_bound(a+1,a+j,(1<<i+2)-2-a[j])-lower_bound(a+1,a+j,(1<<i+1)+(1<<i)-a[j]))&1)ans^=(1<<i);
		}
	}
	printf("%d\n",ans);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值