题目链接
题意
有$n$个人,每个人有钱,有种糖,每个糖元,每个人会尽量多的买他喜欢的糖,现在问有多少$(i,j)$满足第$i$个人买第$j$种糖,最后剩$k$元。
思路
若有,则,我们不妨设,则,我们找到$x$的因子作为,且必须有,此时,对于这样一对就会对答案产生贡献。
我们可以把k从大到小枚举,记录所有比当前大的数字的倍数作为$x$,那么所有存在的会和对应的差$k$的产生贡献。
用bitset优化上面的算法。(学习一下手写bitset)
1 |
|
手写bitset。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
using namespace std;
typedef long long ll;
void err(){cout << "\033[39;0m" << endl;}
template<template<typename...> class T, typename t, typename... A>
void err(T<t> a, A... x){for (auto v: a) cout << v << ' '; err(x...);}
template<typename T, typename... A>
void err(T a, A... x){cout << a << ' '; err(x...);}
const int N = 5e4 + 5, SN = 5e4 + 5;
unsigned int BitReverse(unsigned int x) {
static unsigned int a[1 << 16 | 1], now = 1;
if(now) {
a[0] = now = 0;
REP(i, 1, 1 << 16) a[i] = (a[i >> 1] >> 1) | ((i & 1) << 15);
}
return a[x >> 16] | (a[x & 65535] << 16);
}
int BitNum(unsigned int x) {
static unsigned int a[1 << 16 | 1], now = 1;
if(now) {
a[0] = now = 0;
REP(i, 1, 1 << 16) a[i] = a[i >> 1] + (i & 1);
}
return a[x >> 16] + a[x & 65535];
}
struct bitset {
static const int BIT = 32;
static const int SIZE = SN / BIT + 1;
unsigned int a[SIZE];
bitset();
unsigned int & operator [] (const int);
const unsigned int & operator [] (const int) const;
bitset operator & (const bitset &) const;
bitset operator | (const bitset &) const;
bitset operator ^ (const bitset &) const;
bitset operator << (int) const;
bitset operator >> (int) const;
bitset & operator &= (const bitset &);
bitset & operator |= (const bitset &);
bitset & operator ^= (const bitset &);
bitset & operator <<= (int);
bitset & operator >>= (int);
bitset operator ~ () const;
// reverse the binary bit in [0, x)
// "000110010".Reverse(5) = "000001001"
bitset Reverse(int x) const ;
// set the xth binary bit value to f
void Set(int x, bool f = true);
// set all binary bit value to 0
void Clear();
// return the xth binary bit value
bool CheckBit(int x) const ;
// return the number of one in binary bit value
int AllBit() const;
void Flip(int x);
};
bitset::bitset() {memset(a, 0, sizeof a);}
unsigned int & bitset::operator [] (const int x) {
return a[x];
}
const unsigned int & bitset::operator [] (const int x) const {
return a[x];
}
bitset bitset::operator & (const bitset &x) const {
bitset ans;
REP(i, 0, SIZE) ans[i] = x[i] & a[i];
return ans;
}
bitset bitset::operator | (const bitset &x) const {
bitset ans;
REP(i, 0, SIZE) ans[i] = x[i] | a[i];
return ans;
}
bitset bitset::operator ^ (const bitset &x) const {
bitset ans;
REP(i, 0, SIZE) ans[i] = x[i] ^ a[i];
return ans;
}
bitset bitset::operator << (int x) const {
bitset ans;
int y = x >> 5, z = x & 31;
if(z)
DFR(i, SIZE - 1, y + 1)
ans[i] = (a[i - y] << z) | (a[i - y - 1] >> (BIT - z));
else
DFR(i, SIZE - 1, y + 1)
ans[i] = a[i - y];
ans[y] = a[0] << z;
return ans;
}
bitset bitset::operator >> (int x) const {
bitset ans;
int y = x >> 5, z = x & 31;
if(z)
REP(i, 0, SIZE - y - 1)
ans[i] = (a[i + y] >> z) | (a[i + y + 1] << (BIT - z));
else
REP(i, 0, SIZE - y - 1)
ans[i] = a[i + y];
ans[SIZE - y - 1] = a[SIZE - 1] >> z;
return ans;
}
bitset & bitset::operator &= (const bitset &x) {
REP(i, 0, SIZE) a[i] &= x[i];
return *this;
}
bitset & bitset::operator |= (const bitset &x) {
REP(i, 0, SIZE) a[i] |= x[i];
return *this;
}
bitset & bitset::operator ^= (const bitset &x) {
REP(i, 0, SIZE) a[i] ^= x[i];
return *this;
}
bitset & bitset::operator <<= (int x) {
int y = x >> 5, z = x & 31;
if(z)
DFR(i, SIZE - 1, y + 1)
a[i] = (a[i - y] << z) | (a[i - y - 1] >> (BIT - z));
else
DFR(i, SIZE - 1, y + 1)
a[i] = a[i - y];
a[y] = a[0] << z;
REP(i, 0, y) a[i] = 0;
return *this;
}
bitset & bitset::operator >>= (int x) {
int y = x >> 5, z = x & 31;
if(z)
REP(i, 0, SIZE - y - 1)
a[i] = (a[i + y] >> z) | (a[i + y + 1] << (BIT - z));
else
REP(i, 0, SIZE - y - 1)
a[i] = a[i + y];
a[SIZE - y - 1] = a[SIZE - 1] >> z;
REP(i, SIZE - y, SIZE) a[i] = 0;
return *this;
}
bitset bitset::operator ~ () const {
bitset ans;
REP(i, 0, SIZE) ans[i] = ~a[i];
return ans;
}
bitset bitset::Reverse(int x) const {
bitset ans;
int y = x >> 5, z = x & 31;
FOR(i, 0, y) ans[i] = BitReverse(a[y - i]);
return ans >> (BIT - z);
}
void bitset::Set(int x, bool f) {
int y = x >> 5, z = x & 31;
a[y] |= 1 << z;
if(!f) a[y] ^= 1 << z;
}
void bitset::Clear() {
memset(a, 0, sizeof a);
}
int bitset::AllBit() const {
int ans = 0;
REP(i, 0, SIZE) ans += BitNum(a[i]);
return ans;
}
bool bitset::CheckBit(int x) const {
int y = x >> 5, z = x & 31;
return a[y] >> z & 1;
}
void bitset::Flip(int x)
{
int y = x >> 5, z = x & 31;
a[y] ^= 1 << z;
}
//Bitset
bitset A, B, ans;
int ret[N];
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
int n, m, q;
scanf("%d%d%d", &n, &m, &q);
int maxa = 0, maxb = 0;
A.Clear();
B.Clear();
ans.Clear();
memset(ret, 0, sizeof(ret));
for (int i = 1; i <= n; i++)
{
int a;
scanf("%d", &a);
maxa = max(maxa, a);
A.Set(a);
}
for (int i = 1; i <= m; i++)
{
int b;
scanf("%d", &b);
maxb = max(maxb, b);
B.Set(b);
}
for (int k = maxb; k >= 0; k--)
{
ret[k] = ((A >> k) & ans).AllBit() & 1;
if (B.CheckBit(k))
for (int j = 0; j <= maxa; j += k)
ans.Flip(j);
}
while (q--)
{
int k;
scanf("%d", &k);
printf("%d\n", ret[k]);
}
}
return 0;
}