CF1322B Present
题目
像位运算这一类二进制的两位之间互不影响,所以首先考虑拆位。
假设目前在考虑第
k
k
k 位。那么我们只会关心一个数二进制
[
1
,
k
]
[1,k]
[1,k] 位,换言之,我们只关心一个数模
2
k
+
1
2^{k+1}
2k+1 后的数。并且我们注意到两个数相加后第
k
k
k 位等于
1
1
1 当且仅当两数取模后的和在
[
2
k
,
2
k
+
1
−
1
]
[2^k,2^{k+1}-1]
[2k,2k+1−1] 或
[
2
k
+
1
+
2
k
,
2
k
+
2
−
2
]
[2^{k+1}+2^k,2^{k+2}-2]
[2k+1+2k,2k+2−2] 的范围内,这个计数可以双指针解决。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<map>
#include<queue>
using namespace std;
const int N=4e5+5;
int n,ans;
int val[N],qwq[N];
inline int read()
{
int s=0,t=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')t=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
return s*t;
}
inline int calc(int ql,int qr)
{
if(ql>qr) return 0;
int l=1,r=1;
int res=0;
for(int i=n;i;--i)
{
while(l+1<=n&&qwq[i]+qwq[l]<ql) ++l;
while(r+1<=n&&qwq[i]+qwq[r+1]<=qr) ++r;
if(qwq[i]+qwq[l]<ql||qwq[i]+qwq[r]>qr) continue;
res+=r-l+1;
if(l<=i&&i<=r) --res;
}
return (res>>1)&1;
}
int main()
{
n=read();
for(int i=1;i<=n;++i) val[i]=read();
for(int i=0;i<=24;++i)
{
for(int j=1;j<=n;++j) qwq[j]=val[j]&((1<<i+1)-1);
sort(qwq+1,qwq+n+1);
ans+=(calc(1<<i,(1<<i+1)-1)^calc(3<<i,(1<<i+2)-2))*(1<<i);
}
printf("%d",ans);
return 0;
}
P3293「SCOI2016」美味
题目
有着与前一题类似的做法,只不过上了点数据结构了。