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;
    } 

    (这是后一种做法)

  • 相关阅读:
    自动化测试工具Gauge--contexts 与 Tear Down steps
    Redis官网第一次闲逛
    针对 《Linux就该这么学》 之 “第三章---管道符、重定向、环境变量” 摘抄、操练及拓展
    父shell 和 子shell; shell脚本的几种执行方式
    麒麟操作系统操练Linux基操
    HTTP代理
    gcc/g++ 安全编码
    golang 生成rsa秘钥对
    depth of feild
    Emission pass
  • 原文地址:https://www.cnblogs.com/Yuhuger/p/8619161.html
Copyright © 2011-2022 走看看