Codeforces Round #626 (Div. 1, based on Moscow Open Olympiad in Informatics) B. Present(位运算+二分)

题目链接
Codeforces Round #626 (Div. 1, based on Moscow Open Olympiad in Informatics) B. Present(位运算+二分)_第1张图片
思路:我们知道异或的话如果某一位上1的个数是奇数的话,那么这一位最后异或出来的也是1,我们就从位数来考虑,考虑一下当前位有几个1,假设当前位为3,表示成二进制就是1000,那么我们遍历每一个元素,看看对于当前元素来说,谁加它才会满足第3位为1,假设ai+aj第3位为1的话,他的区间一定实在(111,10000】以及(10111,11111】(这里解释一下第二个区间因为ai+aj有可能相加会产生进行,他们他们的二进制数会有可能会比1000大),然后剩下的就是二分查找这个区间了。

#include
using namespace std;
typedef long long ll;
const int maxn=4e5+5;
ll sum=0,a[maxn],b[maxn];
int main()
{
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;++i) scanf("%lld",&a[i]);
	for(ll i=0;i<=25;++i)
	{
		for(int j=1;j<=n;++j)
		b[j]=a[j]&((1LL<<(i+1))-1);
		sort(b+1,b+1+n);
		ll ans=0;
		for(int j=1;j<=n;++j)
		{
			ll r=upper_bound(b+1+j,b+1+n,(1LL<<(i+1))-1-b[j])-b-1;
			ll l=upper_bound(b+1+j,b+1+n,(1LL<<i)-1-b[j])-b-1;
			ans+=r-l+1;
			r=upper_bound(b+1+j,b+1+n,(1LL<<(i+2))-1-b[j])-b-1;
			l=upper_bound(b+1+j,b+1+n,(1LL<<(i+1))+(1LL<<i)-1-b[j])-b-1;
			ans+=r-l+1;
		}
		if(ans&1) sum+=(1LL<<i);
	}
	printf("%lld\n",sum);
}

你可能感兴趣的:(二分)