【异或运算与加减法的禁断结合】题解:P11651 [COCI 2024/2025 #4] Xor
复健笑传之 Count Count Bit。
还记得第一次看见位运算于加减法同时出现,心情是多么的目力。究竟是谁发明的这几把玩意!然后便思索如何处理进位的问题。然后不知不觉摸鱼去了。
然后我就退役了。然后我到现在都不知道这一类题该怎么做。
下文中,对于二进制位,我们从
求一堆东西的异或和。我们可以枚举它的每一个二进制位,尝试判断上面是
答案是一堆数的异或和。所以,如果我们想知道第
给定两个正整数
A 和B ,快速判断A+B 的二进制的第i 位是0 还是1 。
我们当然可以直接加起来在上左移右移之类的东西。但这样我们就回到原点了。毕竟我们面对的不是一对数,而是很多对数。位运算是不进位的,加减法是进位的。如果它们混在一起,会对优化带来麻烦。我们必须转化或去掉其中之一。
但我不会。
但首先,我们注意到,如果只是关注第
然后我们想,假设
就像下面这样上面这几句话或许有点拗口
上面红的部分就是我们说的第
将上面的二进制变成十进制就是这样:
然后你就把左移右移改成了大小比较,然后就能和加减法兼容了。然后你就会这道题了。然后我会了。然后我忘了。然后我退役了。
最右边的
求一个数组里有多少个
然后这道题就做完了。
哦孩子们我们还要满足
哦孩子们这题卡常我懒得基数排序了直接用快读日过去了。
#include <bits/stdc++.h>
namespace IO{
char buff[1<<21],*P1OfFastIO=buff,*P2OfFastIO=buff;
#define getch() (P1OfFastIO==P2OfFastIO&&(P2OfFastIO=((P1OfFastIO=buff)+fread(buff,1,1<<21,stdin)),P1OfFastIO==P2OfFastIO)?EOF:*P1OfFastIO++)
template<typename T>
void read(T &x){char CHOfFastIO=getch();int fl=1;x=0;while(CHOfFastIO>'9'||CHOfFastIO<'0'){if(CHOfFastIO=='-')fl=-1;CHOfFastIO=getch();}while(CHOfFastIO<='9'&&CHOfFastIO>='0'){x=x*10+CHOfFastIO-48;CHOfFastIO=getch();}x*=fl;}
template<typename T,typename ...Args>
void read(T &x,Args& ...args){read(x);read(args...);}
char obuf[1<<21],*P3OfFastIO=obuf;
inline void putch(char CHOfFastIO){if(P3OfFastIO-obuf<(1<<21))*P3OfFastIO++=CHOfFastIO;else fwrite(obuf,P3OfFastIO-obuf,1,stdout),P3OfFastIO=obuf,*P3OfFastIO++=CHOfFastIO;}
char CHOfFastIO[100];template<typename T>
void write(T x){if(!x)return putch('0');if(x<0)putch('-'),x*=-1;int top=0;while(x)CHOfFastIO[++top]=x%10+48,x/=10;while(top)putch(CHOfFastIO[top]),top--;}
template<typename T,typename ...Args>
void write(T x,Args ...args){write(x);write(args...);}
inline void flush(){fwrite(obuf,P3OfFastIO-obuf,1,stdout);}
}using namespace IO;
using namespace std;
typedef long long LL;
const int maxn=5e5+7;
const LL inf=1e18+7;
LL N,a[maxn],b[maxn];
inline LL solve(LL p){
LL ret=0;
LL mod=(1LL<<(p+1)),u=(1LL<<p);
for(int i=1;i<=N;i++)b[i]=a[i]%mod;
sort(b+1,b+N+1);b[N+1]=inf;
//for(int i=1;i<=N;i++)cout<<b[i]<<' ';cout<<endl;
for(int i=1,p=N+1;i<=N;i++){
while(p!=0&&b[p]+b[i]>=u)--p;
ret+=N-max(p,i-1);
}
//cout<<"ret: "<<ret<<endl;
for(int i=1,p=N+1;i<=N;i++){
while(p!=0&&b[p]+b[i]>=u*2)--p;
ret-=N-max(p,i-1);
}
//cout<<"ret: "<<ret<<endl;
for(int i=1,p=N+1;i<=N;i++){
while(p!=0&&b[p]+b[i]>=u*3)--p;
ret+=N-max(p,i-1);
}
//cout<<"ret: "<<ret<<endl;
return ret&1;
}
int main(){
//scanf("%lld",&N);
read(N);
//for(int i=1;i<=N;i++)scanf("%lld",&a[i]);
for(int i=1;i<=N;i++)read(a[i]);
LL ans=0;
for(int p=0;p<=30;p++)
if(solve(p))ans|=(1LL<<p);
//printf("%lld",ans);
write(ans);flush();
return 0;
}