2017 Multi-University Training Contest

来源:互联网 发布:苏联暴行知乎 编辑:程序博客网 时间:2024/06/10 10:05




题意:

给你两个数组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");elseprintf("0\n");}}return 0;}/*110 10 101 18 22 26 38 42 59 64 77 1083 4 8 16 24 38 54 56 57 760 1 5 8 15 23 32 44 45 48*/
原创粉丝点击