题意:
给你两个数组A,B,数组中每个数字范围在[1, 50000]内且不重复,q次询问,每次一个值x,问有多少对(a, b),满足
a%b==x,a∈A,b∈B
实际上这题正解还是n²的暴力
思路很简单,询问直接预处理,枚举每个价格,再枚举价格的倍数
具体题解:http://bestcoder.hdu.edu.cn/blog/2017-multi-university-training-contest-5
只不过因为每个价格只会出现1次,最后答案又是对2取模
所以整个过程只有数字0和1出现,这样的话你一个int型就可以保存32个数据了,而不是保存一个整型
整体复杂度就降为(n²/32),居然就可以过
因为bieset操作受限,没法将一个区间提出来
(假设枚举到价格x,倍数i,很显然A数组[x*i, x*i+x-1]这个区间对答案区间[0, x-1]有贡献)
所以要手写bitset
第一次写感觉挺提麻烦的,具体看程序
#include<stdio.h>
#include<string.h>
#include<bitset>
#include<algorithm>
using namespace std;
bitset<50005> pri;
unsigned int buy[1605], ans[1605];
int main(void)
{
int T, n, m, k, i, j, q, x, now, temp, num;
scanf("%d", &T);
while(T--)
{
scanf("%d%d%d", &n, &m, &q);
memset(ans, 0, sizeof(ans));
memset(buy, 0, sizeof(buy));
pri.reset();
for(i=1;i<=n;i++)
{
scanf("%d", &x);
buy[x/32] |= 1<<(x%32);
}
for(i=1;i<=m;i++)
{
scanf("%d", &x);
pri[x] = 1;
}
for(i=1;i<=50000;i++)
{
if(pri[i]==0)
continue;
for(j=0;j<=50000;j+=i)
{
now = j, temp = min(j+i-1, 50000);
for(k=0;k<=(temp-j)/32-1;k++) //一般来讲都是ans[k]加上buy[now]的后半部分以及buy[now+1]的前半部分
{
ans[k] ^= buy[now/32]>>(now%32); //buy[now]的后半部分往前移动和ans[k]异或
now += 32;
ans[k] ^= (buy[now/32]&((1<<now%32)-1))<<(32-now%32); //buy[now+1]的左半部分往后移动和ans[k]异或
}
for(num=now;now<=temp;now++)
{
if(buy[now/32]&(1<<(now%32))) //最后一点直接暴力,每一位单独异或上去
ans[k] ^= (1<<(now-num));
}
}
}
while(q--)
{
scanf("%d", &x);
if(ans[x/32]&(1<<(x%32)))
printf("1\n");
else
printf("0\n");
}
}
return 0;
}
/*
1
10 10 10
1 18 22 26 38 42 59 64 77 108
3 4 8 16 24 38 54 56 57 76
0 1 5 8 15 23 32 44 45 48
*/