CodeForces 1322B - Present二进制
Posted 1024-xzx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces 1322B - Present二进制相关的知识,希望对你有一定的参考价值。
题意:
求 ((a_1+a_2)igoplus(a_1+a_3)igoplus ... igoplus(a_{n-1}+a_n))
数据范围:(2leq n leq 4*10^5 ,1leq a_i leq 10^7)
分析:
对答案的每一位二进制位单独考虑。
??对于答案的第 (k) 位,如果要使其为 (1) ,那么必然有奇数个第 (k) 位为 (1) 的 ((a_i+a_j)) 进行异或。对于每个数,第 (k) 位之前的位置的数并不会影响该结果,因此可以让每个数对 (2^{(k+1)}) 进行取模,使每个数处于 ([0,2^{(k+1)}-1]) 内,则((a_i+a_j)in [0,2^{(k+2)}-2])。要使 ((a_i+a_j)) 的第 (k) 位为 (1) ,则其取值范围为 ([2^k,2^{(k+1)}-1]) 或者 ([2^{(k+1)}+2^k,2^{(k+2)}-2])。可以对取模后的数进行排序,枚举每个数,然后二分求出有多少个数和它相加的和在上述的两个区间内。如果个数为奇数个,即可以异或到答案中。
二分时,要在当前枚举数前面进行寻找。
以后看到和位运算有关的题目,可以往二进制方面多想想。
复杂度:(O(n*logn*logn))
代码:
#include <bits/stdc++.h>
using namespace std;
const int N=4e5+5;
int a[N],b[N];
int main()
{
int n,L,R,t,ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int k=0;k<=24;k++)//枚举答案的二进制位
{
int mod=1<<(k+1);//高位不影响
for(int i=1;i<=n;i++)
b[i]=a[i]%mod;//[0,2^(k+1)-1]
sort(b+1,b+1+n);
for(int i=1;i<=n;i++)
{
L=max(0,(1<<k)-b[i]);R=(1<<(k+1))-1-b[i];
t=upper_bound(b+1,b+i,R)-lower_bound(b+1,b+i,L);
if(t&1)
ans^=(1<<k);
L=max(0,(1<<(k+1))+(1<<k)-b[i]);R=(1<<(k+2))-2-b[i];
t=upper_bound(b+1,b+i,R)-lower_bound(b+1,b+i,L);
if(t&1)
ans^=(1<<k);
}
}
printf("%d
",ans);
return 0;
}
以上是关于CodeForces 1322B - Present二进制的主要内容,如果未能解决你的问题,请参考以下文章
thread-local-allocation-buffers
使用Powerpoint for macos自动合并pptx文件