题意:
给定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
using namespace std;
const int N = 50000+5;
bitseta,b,ans;
bitsetbb;
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