[补题]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次询问每次给一个(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;
}
原文地址:https://www.cnblogs.com/yoshinow2001/p/14651002.html