Codeforces Round #626 Div2 D

比赛链接:

Codeforces Round #626 (Div. 2, based on Moscow Open Olympiad in Informatics)

D. Present

题意:

给定大小为$n$的a数组,求下面式子的结果:

$$ (a_1 + a_2) \oplus (a_1 + a_3) \oplus \ldots \oplus (a_1 + a_n) \\ \oplus (a_2 + a_3) \oplus \ldots \oplus (a_2 + a_n) \\ \ldots \\ \oplus (a_{n-1} + a_n) \\$$

分析:

这题看了题解补的

分别求结果的第$k$(以0开始计数)位是否为1

显然,我们不需要关心每个数第$k$位以上是什么,那么对数组取模$2^{k+1}$

两个数的和的第$k$位为1时,才对答案的第$k$位有贡献,那么和的第$k$位为1需要属于$[2^k; 2^{k+1})$或者$[2^{k+1} + 2^k; 2^{k+2} - 2]$,求出这样的和的对数,如果对数为奇数,那么答案的第$k$位为1,否则为0

求对数可以用二分查找来求

AC代码:

#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,a,b) for (int i=b;i>=a;i--)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define SZ(x) ((int)(x).size())

typedef long long ll;
typedef vector<int> VI;
typedef pair<int,int> PII;

const ll mod=1e5+7;
const int maxn=4e5+7;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}

int ans,a[maxn],b[maxn],n;
int pow2[30];

int cal(int k){
    ll res=0;
    rep(i,1,n)b[i]=a[i]%(1<<(k+1));
    sort(b+1,b+1+n);
    rep(i,1,n){
        int x=b[i];
//        cout<<"x="<<x<<endl;
        if(x*2>=pow2[k]&&x*2<=pow2[k+1]-1)res--;
        else if(x*2>=pow2[k]+pow2[k+1])res--;
        res+=upper_bound(b+1,b+1+n,pow2[k+1]-1-x)-lower_bound(b+1,b+1+n,pow2[k]-x);
        res+=upper_bound(b+1,b+1+n,1e9)-lower_bound(b+1,b+1+n,pow2[k]+pow2[k+1]-x);
    }
//    cout<<"res="<<res<<endl;
    return res/2%2;
}

int main() {
//    cout<<(1<<24)<<endl;
    rep(i,0,29)pow2[i]=(1<<i);
    scanf("%d",&n);
    rep(i,1,n)scanf("%d",&a[i]);
    rep(i,0,25)if(cal(i))ans+=(1<<i);
    printf("%d\n",ans);

    return 0;
}

  

总结:

猜你喜欢

转载自www.cnblogs.com/carcar/p/12442211.html