hdu 6085 Rikka with Candies(bitset容器)

Rikka with Candies

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


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


首先从B的最大值开始枚举余数k,答案是预先处理出来的,类似于打个表,将每一个余数为k的询问存在ans[k]中

在每一次余数k枚举中,因为a%b==k --> (a[]-k)%b[]==0,所以就遍历a[]中的数,记录(ai-k)%b的数量(b是b[]中比k大的数),

即就是找a[]-k中有多少数是b[]中bi比k大的那些数的倍数

再每一次处理完余数为k的答案是,若b[]中b[i]等于当前枚举的k,那么就枚举b[i]的倍数,并将他们记录在b'b[]中。


在所有数组中,用到了bitset,相当于一个visit数组,若i在a中出现过,那么a[i]=1,否则a[i]=0



#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<bitset>
using namespace std;

const int N = 50000+10;

bitset<N> a,bb,ans,b;  //ans[i]表示余数为i的答案%2的结果,bb是b的倍数,bb[i]=1 : 有奇数个y满足 i%b[y]==0
int MaxK;  

void solve()
{
	bb.reset();		
	ans.reset();

	for(int i=MaxK;i>=0;i--)  //枚举k(i)
	{
		ans[i]=(bb&(a>>i)).count()&1;//存在多少个(a-i)%b=0,bb现在是所有b中>i的数的倍数(是>i的倍数就置为1),对于偶数个数的公倍数就置为0,奇数个数的公倍数置为1
		if(b[i])   //枚举b[i]倍数,若这个i在b数组里,就枚举其倍数,用于计算之后余数i‘(<现在的i)的情况
		{
			for(int j=0;j<N;j+=i)   //将上一个i1与这一个i2的公倍数置为0的原因是,若a[这个公倍数+余数k]=1,说明a中有一个数可以同时%i1=k,%i2=k
				bb.flip(j);        //但这样有偶数次,对答案%2的答案并不影响例如,a中有321,b中有17,18且MAXk=18,余数有15
		}                             //因为(321-15)%17==0 ,(321-15)%18==0,所以这样对%2的结果不影响,所以在两次(对17的倍数,对18的倍数)取反后,b[306(=321-15)]=0,这样对答案是无影响的
	}
}

int main()
{
	int t,n,m,q,x;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d%d",&n,&m,&q);
		a.reset();
		b.reset();
		for(int i=0;i<n;i++) scanf("%d",&x),a.set(x);
		MaxK=-1;
		for(int i=0;i<m;i++)
		{
			scanf("%d",&x);
			b.set(x);
			MaxK=max(MaxK,x);
		}
		solve();
		for(int i=0;i<q;i++)
		{
			scanf("%d",&x);
			puts(ans[x]?"1":"0");
		}
	}
	return 0;
}






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值