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

题目传送门

题目大意

题目很好理解,有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 50005
bitset<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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值