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)(1≤i≤n,1≤j≤m) 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?
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)(1≤i≤n,1≤j≤m) 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(1≤t≤5)
, the number of the testcases.
For each testcase, the first line contains three numbers n,m,q(1≤n,m,q≤50000) .
The second line contains n numbers Ai(1≤Ai≤50000) and the third line contains m numbers Bi(1≤Bi≤50000) .
Then the fourth line contains q numbers ki(0≤ki<maxBi) , which describes the queries.
It is guaranteed that Ai≠Aj,Bi≠Bj for all i≠j .
For each testcase, the first line contains three numbers n,m,q(1≤n,m,q≤50000) .
The second line contains n numbers Ai(1≤Ai≤50000) and the third line contains m numbers Bi(1≤Bi≤50000) .
Then the fourth line contains q numbers ki(0≤ki<maxBi) , which describes the queries.
It is guaranteed that Ai≠Aj,Bi≠Bj for all i≠j .
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;
}