CF1322B - Present 思维

CF1322B - Present

题意

N N N个数 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1,a2,...,an,现在求 ( a 1 + a 2 ) ⊕ ( a 1 + a 3 ) ⊕ ⋅ ⋅ ⋅ ⊕ ( a n − 1 + a n ) (a_1+a_2)⊕(a_1+a_3)⊕···⊕(a_{n-1}+a_n) (a1+a2)(a1+a3)(an1+an) N ≤ 400000 N\leq400000 N400000

题解

直接算是不行的
这里考虑计算二进制下 a n s ans ans的每一位
对于 a n s ans ans的第 k k k位答案,我们只需要考虑数 a i a_i ai [ 0 , k ] [0,k] [0,k]位,因为超过 k k k位对第 k k k位没有影响
所以我们记 b i = a i % 2 k + 1 b_i=a_i\%2^{k+1} bi=ai%2k+1,这样就保留了 [ 0 , k ] [0,k] [0,k]位的影响
然后我们要第 k k k位结果是 1 1 1 b i + b j b_i+b_j bi+bj
而第 k k k位为1的数的范围为 [ 2 k , 2 k + 1 − 1 ] [2^k,2^{k+1}-1] [2k,2k+11] [ 2 k + 1 + 2 k , 2 k + 2 − 2 ] [2^{k+1}+2^k, 2^{k+2}-2] [2k+1+2k,2k+22]
后面 2 k + 2 − 2 2^{k+2}-2 2k+22这么来的: b [ i ] ∈ [ 0 , 2 k + 1 − 1 ] b[i]∈[0,2^{k+1}-1] b[i][0,2k+11],这里两个数,所以就是 2 k + 2 − 2 2^{k+2}-2 2k+22
可以通过枚举 b i b_i bi求得对应的 b j b_j bj数量即可

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX = 4e5 + 10;

int N;
int a[MAX], b[MAX];

int pos(int x) { return lower_bound(b + 1, b + 1 + N, x) - b; }

int main() {
    scanf("%d", &N);
    for (int i = 1; i <= N; i++) scanf("%d", &a[i]);
    int ans = 0;
    for (int bit = 0; bit <= 25; bit++) {
        int num = 1 << bit;
        for (int i = 1; i <= N; i++) b[i] = (a[i] & (2 * num - 1));//和a[i] % (2 * num - 1)一样的
        sort(b + 1, b + 1 + N);//排序
        int cnt = 0;
        for (int i = 1; i <= N; i++) {
            cnt += pos(4 * num - b[i] - 1) - pos(3 * num - b[i]);//[3 * num, 4 * num - 2]间的数
            cnt += pos(2 * num - b[i]) - pos(num - b[i]);//[num, 2 * num - 1]间的数
            if ((2 * b[i]) & num) cnt--;//如果b[i]+b[i]的第k位是1, 就减去这种
        }
        if ((cnt / 2) & 1) ans ^= 1 << bit;//这里cnt/2是因为我们会算b[i]+b[j]和b[j]+b[i]两种
    }
    printf("%d\n", ans);

    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值