[补题]2017多校5A/HDU6085-Rikka with Candies-bitset优化
2017多校5-A/bitset优化
http://acm.hdu.edu.cn/showproblem.php?pid=6085
题意:给序列\(A[1,\dots,n]\)和\(B[1,\dots,m]\),q次询问每次给一个\(d\leq \max B_i\),问有多少对\((i,j):A_i\bmod B_i=d\),答案对2取模,\(n,m,q\leq 5\times 10^4\)。
一开始读错题意以为右边也是取模
看题解会的,思路来自于注意到\(A\bmod B=d (d<B)\iff \exist k\in N:A=kb+d\),也就是\(A-d=kb\),不管是左边的形式,还是对2取模,大概都需要能够想到尝试bitset的优化,用bitset
存一个A和B,如果是暴力的话就直接是:
rep(i,1,m){
scanf("%d",&B[i]);
for(int j=0;j<=N-5;j+=B[i])b[i].set(j);
}
rep(i,1,q){
int d;scanf("%d",&d);
int ret=0;
rep(j,1,m)if(d<B[j])ret^=(((a>>d)&b[j]).count())&1;
printf("%d\n",ret);
}
这样做是个大暴力,我好像出不了奇迹,那就优化呗,暴力的瓶颈在于每次都要对每一个询问\(d\)都要遍历每一个\(b\),一个个取and,于是其实我们就考虑这\(m\)个b的bitset的信息能不能合并起来?
对某个位置\(k\),合并之后的\(B[k]=\oplus_{i=1}^m B[i][k]\)的结果(以为是要奇偶性,相加相当于异或),而又要保证\(d<B\),那我们就是从大到小枚举\(B\)啦~
rep(i,1,m){
int x;scanf("%d",&x);
mx=max(mx,x);b.set(x);
}
for(int i=mx;i>=0;i--){
ret[i]=((a>>i)&B).count()&1;
if(b[i])
for(int k=0;k<=N-5;k+=i)B[k]=B[k]^1;
}