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; }
(这是后一种做法)