AtCoder Regular Contest 092 D(二进制性质)

偶然听到打arc的同学讨论这题,就听了一下题面。

之后断断续续想了两天,又断断续续打了两天。

题意非常简洁

输入a数组,b数组

对于每一个i,j ans^=a[i]+b[j]

输出ans

数组长度100000

a,b的元素小于2^28

 

二进制加法有一个优良的性质,在不考虑进位的情况下与异或等价。

所以,这题只需要处理出每一位上的进位个数即可。

具体实现,如果内部用快排和单调性做,是n (log^2 值域)

如果根据性质用基排从低位到高位和单调性做,是一个log

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=200010;
int n,a[N],m,b[N],ty,bucket[10],t[N],d[N];
bool cmp(int x,int y){
    return (x&ty)<(y&ty);
}
void hsort(int gg,int *r){
    for (int i=1; i<=n; ++i) t[i]=r[i];
    bucket[0]=bucket[1]=0;
    for (int i=1; i<=n; ++i) ++bucket[(r[i]>>gg)&1];
    bucket[1]+=bucket[0];
    for (int i=n; i>=1; --i) d[bucket[(r[i]>>gg)&1]--]=i;
    for (int i=1; i<=n; ++i) r[i]=t[d[i]];
}
int jw(int gg){
    //sort(a+1,a+n+1,cmp);
    //sort(b+1,b+m+1,cmp);
    hsort(gg,a); hsort(gg,b);
    int dpos=m+1,res(0);
    for (int i=1; i<=n; ++i){
        while (dpos>1&&(b[dpos-1]&ty)+(a[i]&ty)>ty) --dpos;
        //cerr<<dpos<<" "<<ty<<endl; 
        if ((m+1-dpos)&1) res^=1;
    }
    return res;
}
void test(){
    for (int i=1; i<=n; ++i) a[i]=rand()%8;
    hsort(0,a);
    for (int i=1; i<=n; ++i) printf("%d ",a[i]); puts("");
    hsort(1,a);
    for (int i=1; i<=n; ++i) printf("%d ",a[i]); puts("");
    hsort(2,a);
    for (int i=1; i<=n; ++i) printf("%d ",a[i]); puts("");
}
int main(){
    scanf("%d",&n); m=n;    
    //test();
    for (int i=1; i<=n; ++i) scanf("%d",&a[i]);
    for (int i=1; i<=m; ++i) scanf("%d",&b[i]);
    int ans=0;
    for (int i=0; i<29; ++i){
        if (i) ans^=jw(i-1)<<i;
        //cerr<<"ans"<<ans;
        ty|=1<<i;
        if (m&1)
        for (int j=1; j<=n; ++j) ans^=a[j]&(1<<i);
        //cerr<<"i"<<i<<" "<<ans<<" "<<ty<<endl;
        if (n&1)
        for (int j=1; j<=m; ++j) ans^=b[j]&(1<<i);
        //cerr<<"i"<<i<<" "<<ans<<" "<<ty<<endl;
    }
    cout<<ans<<endl;
} 

(这是后一种做法)

posted @ 2018-03-21 19:47  Yuhuger  阅读(281)  评论(0编辑  收藏  举报