2017多校5-A/bitset优化
http://acm.hdu.edu.cn/showproblem.php?pid=6085
题意:给序列(A[1,dots,n])和(B[1,dots,m]),q次询问每次给一个(dleq max B_i),问有多少对((i,j):A_imod B_i=d),答案对2取模,(n,m,qleq 5 imes 10^4)。
一开始读错题意以为右边也是取模
看题解会的,思路来自于注意到(Amod B=d (d<B)iff exist kin 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
",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;
}