HDU 6085 Rikka with Candies(bitset)
【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=6085
【题目大意】
给出一个数组a一个数组b,以及询问数组c,
问对于每个c有多少对a%b=c,答案对2取模
【题解】
考虑对2取模我们发现答案等价于数字的xor,01状态可以用bitset保存,
在bitset上存a的权值数组,那么每次只要将b*i~b*(i+1)-1的数值xor到答案数组的0~b-1上去即可,
鉴于bitset没有截取区间的功能,我们手写压位,
考虑压32位之后不是32倍数的部分截取起来非常尴尬,
因此我们保存其偏移量为0~31的数组,这样取区间就比较方便了。
【代码】
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int N=10010; struct Bitset{ unsigned int u[N]; void reset(){memset(u,0,sizeof(u));} void set(int x){u[x>>5]|=1<<(x&31);} void flip(int x){u[x>>5]^=1<<(x&31);} bool test(int x){return u[x>>5]&(1<<(x&31));} void reset(int x){if(test(x))flip(x);} }a[32],ans; void Solve(int l,int r){ while((r-l)&31){r--;if(a[0].test(r))ans.flip(r-l);} int m=0; while(l&31)l++,r++,m++; l>>=5; r>>=5; for(int i=l;i<r;i++)ans.u[i-l]^=a[m].u[i]; } int T,n,m,q,x,mx; int main(){ scanf("%d",&T); while(T--){ scanf("%d%d%d",&n,&m,&q); for(int i=0;i<32;i++)a[i].reset(); ans.reset(); mx=0; for(int i=1;i<=n;i++){ scanf("%d",&x); mx=max(x,mx); for(int j=0;j<32;j++)a[j].set(x+j); } for(int i=1;i<=m;i++){ scanf("%d",&x); for(int j=0;j<=mx;j+=x)Solve(j,min(mx+1,j+x)); } while(q--){ scanf("%d",&x); if(ans.test(x))puts("1"); else puts("0"); } }return 0; }
愿你出走半生,归来仍是少年