D. Present (思维,异或)

Posted willems

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了D. Present (思维,异或)相关的知识,希望对你有一定的参考价值。

题目:传送门

题意:让你求

技术图片

 

 

 

 2 <= n <= 400000, 1 <= ai <= 10000000

 

思路:

对每个二进制位单独考虑,若答案的第 i 位二进制位是 1,意味着有奇数对 (j, k) 满足 (aj + ak) 二进制第 i 位是 1.

那么考虑怎么算有多少对 (aj + ak) 满足二进制第 i 位是1.

高于 i 位的二进制位都不会对答案的第 i 位产生影响,那就把高于 i 位的先去掉,取模一下就可以了,取模后 0 <= ai <= 2^(i + 1) - 1.

那  0 <= aj + ak <= 2^(i + 2) - 2

然后,你 aj + ak 的第 i 位二进制位是 1,那么你可能的区间有  [ 2^i, 2^(i + 1) - 1 ], [ 2^(i + 1) + 2^i, 2^(i + 2) - 2 ] 

那你可以枚举 aj,然后二分一下有多少满足条件的 ak 就行了。

 

#include <bits/stdc++.h>
#define LL long long
#define mem(i, j) memset(i, j, sizeof(i))
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define pb push_back
#define make make_pair
#define INF INT_MAX
#define inf LLONG_MAX
#define PI acos(-1)
#define fir first
#define sec second
using namespace std;

const int N = 1e6 + 5;

int a[N], b[N];

int main() {

    int n;
    scanf("%d", &n);
    rep(i, 0, n - 1) scanf("%d", &a[i]);
    int ans = 0;
    rep(k, 0, 24) {
        rep(i, 0, n - 1) b[i] = a[i] % (1 << (k + 1));
        sort(b, b + n);
        rep(i, 0, n - 1) {
            int L = max(0, (1 << k) - b[i]);
            int R = ((1 << (k + 1)) - 1) - b[i];
            int dis = upper_bound(b, b + i, R) - lower_bound(b, b + i, L);
            if(dis & 1) ans = ans ^ (1 << k);

            L = max(0, (1 << (k + 1)) + (1 << k) - b[i]);
            R = ((1 << (k + 2)) - 1) - b[i];
            dis = upper_bound(b, b + i, R) - lower_bound(b, b + i, L);
            if(dis & 1) ans = ans ^ (1 << k);
        }
    }
    printf("%d
", ans);
    return 0;

}

 

以上是关于D. Present (思维,异或)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #628 (Div. 2) D. Ehab the Xorcist(异或,思维题)

Codeforces Round #626 Div2 D. Present(位掩码,二分)

Find your present (位异或)

D. Present按位拆分算贡献

HDU 2095 find your present 异或

Codeforces Beta Round #4 (Div. 2 Only) D. Mysterious Present(LIS)