Rikka with Candies(bitset操作)

来源:互联网 发布:淘宝彩票软件是真的吗 编辑:程序博客网 时间:2024/06/04 19:22

题意:A数组n个数,B数组m个数,q个查询, 每次给出一个k,询问有多少对(i,j), 使得Ai % Bj = k, 输出对数对模2的值 

这道题可以用bitset来做,bitset与数组类似,但其中每一位只能为0或1,用来存储2进制的每一位

用整值类型将第27 位设置为1, 我们这样写
quiz1 |= 1<<27;
而用bitset 来做我们可以写
quizl[ 27 ] = 1;

quiz1.set( 27 );

用两个bitset类来进行操作,第一个ac ,ac.set(i)表示ac中第i位赋值1,用来表示i这个数字是否存在

ans[i]= ( bs & (ac>>i) ).count() &1;  ac向右移了i位,即相当与ac中的每个数都减去了i,这就是bitset的方便之处。

& 运算符 只有两个数都为1才是1, ac和bs两个bitset &一波,就是ac和bs中每一位都相&

返回的是一个bitset 再count(),得到的是这个bitset中1的个数,最后再&1,相当于%2


第二个bs用来存储一系列的被余的数,注意到最终结果%2,所以 bs.flip(j); 这一步可以反转抵消,

例如a为8 b有6和3,那么8%6 和8%3都为2,那么贡献一共有2种,%2后和0是一样的。 

#include<bits/stdc++.h>using namespace std;const int N=50005;int a[N],b[N],k[N],ans[N];bool flag[N];bitset<N> bs,ac;int main(){    std::ios::sync_with_stdio(false);    std::cin.tie(0);    int t,n,m,q;    int maxk;    cin>>t;    while(t--)    {        ac.reset();//ac中每一位赋0        bs.reset();        memset(flag,0,sizeof(flag));        maxk=0;        cin>> n >> m >> q;        for(int i=1;i<=n;i++)        {            cin>>a[i];            ac.set(a[i]);//ac中第a[i]位设为1        }        for(int i=1;i<=m;i++)        {             cin>>b[i];             flag[b[i]]=true;             maxk=max(maxk,b[i]);        }        for(int i=1;i<=q;i++)        {            cin>>k[i];        }        for(int i=maxk;i>=0;i--)        {            ans[i]= ( bs & (ac>>i) ).count() &1;            if(flag[i])            {                for(int j=0;j<=maxk;j+=i)                {                    bs.flip(j);//把bc中第j位反转,0变1,1变0                }            }        }        for(int i=1;i<=q;i++)        {            cout<<ans[k[i]]<<endl;        }    }}