zoukankan      html  css  js  c++  java
  • 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;
    } 

    (这是后一种做法)

  • 相关阅读:
    两句话的区别在于目录的不同。
    关于系统的操作全在这里了。这个看起来很重要。
    屏幕坐标的方法
    改变轴心的操作。
    关于旋转的变换处理方法。
    对其位置
    点边同事移除的办法处理。
    移动的坐标变换
    判断文件是否存在的函数。
    把节点归零处理
  • 原文地址:https://www.cnblogs.com/Yuhuger/p/8619161.html
Copyright © 2011-2022 走看看