Rikka with Candies

Rikka with Candies

Time Limit: 7000/3500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1507    Accepted Submission(s): 660


Problem Description
As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:

There are n children and m kinds of candies. The i th child has Ai dollars and the unit price of the i th kind of candy is Bi . The amount of each kind is infinity.

Each child has his favorite candy, so he will buy this kind of candies as much as possible and will not buy any candies of other kinds. For example, if this child has 10 dollars and the unit price of his favorite candy is 4 dollars, then he will buy two candies and go home with 2 dollars left.

Now Yuta has q queries, each of them gives a number k . For each query, Yuta wants to know the number of the pairs (i,j)(1in,1jm) which satisfies if the i th child’s favorite candy is the j th kind, he will take k dollars home.

To reduce the difficulty, Rikka just need to calculate the answer modulo 2 .

But It is still too difficult for Rikka. Can you help her?
 

Input
The first line contains a number t(1t5) , the number of the testcases.

For each testcase, the first line contains three numbers n,m,q(1n,m,q50000) .

The second line contains n numbers Ai(1Ai50000) and the third line contains m numbers Bi(1Bi50000) .

Then the fourth line contains q numbers ki(0ki<maxBi) , which describes the queries.

It is guaranteed that AiAj,BiBj for all ij .
 

Output
For each query, print a single line with a single 01 digit -- the answer.
 

Sample Input
  
  
1 5 5 5 1 2 3 4 5 1 2 3 4 5 0 1 2 3 4
 

Sample Output
  
  
0 0 0 0 1
 

题意:

     给定A,B两个数组,每个数组中各元素互异,给出q个余数k,求有多少组(i,j)满足Ai%Bj=k。


思路:

     若使Ai%Bj=k,则可得(Ai-k)%Bj=0,其中Bj>k,(即除数大于余数),所以题目演变成为,对于每一个Ai,在B中找到符合条件的Bj使满足题意。每一个Ai对应的符合题目要求的Bj的个数,就是这个Ai对于答案的贡献,再把每一个Ai的贡献相加,模2即得结果。由于我们最后转变成为找B中符合Bj>k的Ai-k的因子数,所以我们把Ai-k当作一个整体看待。记作ai。

     假设我们现在已经得出每一个ai对应的Bj个数是多少,下面介绍如何处理得出的Bj个数。

     假设a中的元素为x1,x2,x3.

     则各bitset的元素值应该为:

 

     a             ……     x1         ……         x2           ……          x3           ……

     bitset a    ……      1         …0…         1            …0…         1            ……

     bitset bb   … x1的合法Bj数  ……   x2的合法Bj数   ……   x3的合法Bj数   ……

 

     即除了bitset a [x1],bitset a [x2],bitset a [x3]值为1以外,bitset A中其余元素均为0。而在bitset bb中,对于我们来讲,只有bitset bb[x]是有效值,其他的值我们都用不到(可能为任何值)。另外,由于,加数和模2与各加数模2相加,所得的结果相同,所以我们在bitset bb中只需要存储0 1即可,即符合条件的Bj个数为偶数就赋0,奇数就赋1。要想把有效值取出来,我们可以用bitset a & bitset bb,这样由于bitset a [x] 为1,(1与任何数相与均为数本身),所以相与之后的bitset就只存在有效值。而由于最后结果只看奇偶,所以可以理解为奇数个Bj对答案贡献为1,偶数个Bj对答案没有贡献,故相与之后的bitset中,1的个数再模2就是最后答案。

     下面介绍如何计算每一个ai所对应的符合条件的Bj数。(即bitset bb的求法)

     由上述分析可得,Bj满足两个条件:

     1. Bj是ai的因子

     2. Bj>k

     由于对于一个确定的数,它的因子数是确定的,所以满足条件的Bj主要受k约束。而由Bj>k可得,k越大,满足条件的Bj就越少,所以我们可以考虑从大到小枚举k。易得k最大不能超过B中的最大值,我们记B中元素的最大值为maxK。则k从maxK开始枚举。

     下面举个例子来说明bitset bb的更新过程。

     假设某一个Ai为14,计算余数k=2的情况,b中的元素为2 5 6 11 12。则此时ai为12,由上述分析我们可以知道,k=2时,符合条件的Bj为6,12。(即14的合法Bj为6,12;14-2的合法因子为6,12)。也就是说当k枚举到2时,bitset bb [12]应该为0。(实际为2,奇1偶0)。下面介绍具体的实现过程。

其bb的值均为k=m时使用的bb值(并非k=m时,bb的更新值)

 

                15 14  13 12   11 10   9  8  7  6      5  4  3  2  1  0

k=12          0   0   0   0     0   0    0  0  0  0      0  0  0  0  0  0

k=11          0   0   0   1     0   0    0  0  0  0      0  0  0  0  0  1        (更新12)

k=10          0   0   0   1     1   0    0  0  0  0      0  0  0  0  0  0(2)   (更新11)

k=9至k=7   0   0   0   1    1   0    0  0  0  0      0  0  0  0  0  0(2)   (不进行更新)

k=6            0   0   0   1     1   0    0  0  0  0      0  0  0  0  0  0(2)   (不进行更新)

k=5            1   0   0   0(2) 1   0    0  0  0  1      0  0  0  0  0  1(3)   (更新6)

k=4            1   0   0   0(2) 1   1    0  0  0  1      1  0  0  0  0  0(4)   (更新5)

k=3            1   0   0   0(2) 1   1    0  0  0  1      1  0  0  0  0  0(4)   (不进行更新)

k=2            1   0   0   0(2) 1   1    0  0  0  1      1  0  0  0  0  0(4)   (不进行更新)

k=1            1   1   0   1(3) 1   0(2) 0  1  0  0(2)  1  1  0  1  0  1(5)   (更新2)

k=1            1   1   0   1(3) 1   0(2) 0  1  0  0(2)  1  1  0  1  0  1(5)   (不进行更新)

 

     根据程序可推知如上表。其中符合k=2时,bitset bb[12]=0。下面对bb的更新作出说明。(下面的bb中若不做特殊说明,均为k=m时bb的使用值,而非更新值)

     由于我们要找的Bj必须符合是ai的因子,所以我们在本例中,B中只有12的因子进行更新时,才会影响到bb[12]的值,所以下面我们只对12的因子进行说明。

     k=12时,12作为B中的最大值,此时B中的所有Bj均不符合Bj>k,所以没有符合条件的Bj,故bb中所有的元素为0。

     k=11时,bb[12]的值更新为1。代表在枚举6之前(B中12的下一个因子),对于所有的k,其满足Bj>k的且为12因子的情况就只有一种,即12。由此我们也可以想到,当k=6时,B中满足Bj>6的因子也只有12一个,所以k=6时,使用的bb[12] 仍然为1。由此可以看出,关于bb[12]的所有更新,都是为了供比k更小的因子计算使用。[重点]

     则在k=5时更新6,是为了方便B中下一个12的因子2的计算。此时bb[12]=0(2),代表B中符合Bj>k且为12因子的Bj有两个,分别为6,12。

     K=3时更新2,亦是同理。

     所以我们在枚举k时,总是先使用bitset bb,再进行更新。


下面介绍几个小点

     1. 由于A,B中元素互异,所以我们可以使用bitset

     2. bitset a,a>>i代表a中所有的元素都减去i

     3. bitset bb[i]中存的是B中符合条件的Bj个数


下面贴上代码:

#include<bits/stdc++.h>
using namespace std;

const int N = 50000+5;

bitset<N>a,b,ans;
bitset<N>bb;

void slove(int maxK)
{
    bb.reset();
    ans.reset();
    for(int i=maxK; i>=0; --i) //枚举k
    {
        ans[i]=(bb&(a>>i)).count()&1;

        if(b[i]!=0)
            for(int j=0; j<N; j+=i)
                bb.flip(j); //把j处的二进制取反
    }
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m,q;
        scanf("%d%d%d",&n,&m,&q);

        a.reset();
        b.reset();

        int maxK=0;
        for(int i=0; i<n; ++i)
        {
            int x;
            scanf("%d",&x);
            a.set(x);//把第x位设置为1
        }
        for(int i=0; i<m; ++i)
        {
            int x;
            scanf("%d",&x);
            b.set(x);
            maxK=max(maxK,x); //取b的最大值
        }

        slove(maxK);

        while(q--)
        {
            int x;
            scanf("%d",&x);
            puts(ans[x]?"1":"0");
        }

    }
    return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值