HDU 6085 Rikka with Candies(2017多校第五场)bitset枚举

来源:互联网 发布:编程猫 李天驰 编辑:程序博客网 时间:2024/06/04 00:22

题目传送门

题目大意

题目很好理解,有n个小朋友,m种糖果,每个小朋友分别有Ai dollars,每种糖果单价分别为Bj dollars,每个小朋友会有一种喜爱的糖果,小朋友只会购买自己喜欢的糖果直到自己的钱不够买为止。现有q个询问,问有几个小朋友会剩 k dollars?

分析

  1. 题目思想为求 A%B=k 的种数,转化一下变成求(A-k)%B=0 的种数,即(A-k)是 B 的倍数的种数,那么我们就来枚举B,然后利用bitset分别标记B的倍数。

  2. 由于只有糖果的单价大于剩下的钱,小朋友才可能会有剩下的钱。所以在枚举过程中我们从大到小枚举 B,这样就保证在计算剩余 k 的时候所有需要的B均已被标记,但是不能先于 k 将所有 B 的倍数均标记。

  3. 这里介绍一下本题中用到的bitset的内容:bitset是C++语言的一个类库,用来处理一系列bit位。
    用bitset存储整型数时,eg:
    bieset<5>a; a.set(2); a.set(3); a 中存储的是01100 ,即用0和1标记。
    a.flip(i); 将 第 i 位取反
    a.reset(); 将a全部置零
    a.count(); 返回a中1的个数

关键代码

ans[i]=(buff&(a>>i)).count()&1; buff 存储当前标记的 B 的倍数, a>>i 等同于 A-k
if(b[i]) for(int j=0;j<=maxa;j+=i) buff.flip(j); 标记B的倍数

下面给出代码

#include<iostream>#include<stdio.h>#include<bitset>using namespace std;#define N 50005bitset<N> a,b,buff,ans;int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n,m,q,num;        int maxa=0;        int maxb=0;        scanf("%d%d%d",&n,&m,&q);        a.reset();        b.reset();        buff.reset();        ans.reset();        for(int i=1;i<=n;i++)            scanf("%d",&num),a.set(num),maxa=max(maxa,num);        for(int j=1;j<=m;j++)            scanf("%d",&num),b.set(num),maxb=max(maxb,num);        for(int i=maxb;i>=0;i--)        {            ans[i]=(buff&(a>>i)).count()&1;            if(b[i])                for(int j=0;j<=maxa;j+=i)                    buff.flip(j);        }        for(int i=1;i<=q;i++)            scanf("%d",&num),printf("%d\n",ans[num]?1:0);    }    return 0;}
阅读全文
0 0
原创粉丝点击