[补题]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;
}
posted @ 2021-04-12 22:48  yoshinow2001  阅读(69)  评论(0编辑  收藏  举报