CodeForces 1322B

题意:

((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;
}

原文地址:https://www.cnblogs.com/1024-xzx/p/12462436.html