CF2061E Kevin and And
题目描述
Kevin 有一个长度为 n n n 的整数序列 a a a。同时,Kevin 拥有 m m m 种魔法类型,其中第 i i i 种魔法可以用整数 b i b_i bi 表示。
Kevin 最多可以执行 k k k 次(可能为零)魔法操作。每次操作中,Kevin 可以执行以下步骤:
- 选择两个索引 i i i( 1 ≤ i ≤ n 1 \leq i \leq n 1≤i≤n)和 j j j( 1 ≤ j ≤ m 1 \leq j \leq m 1≤j≤m),然后将 a i a_i ai 更新为 a i & b j a_i\ \&\ b_j ai & bj。此处 & \& & 表示位与操作。
请计算在执行最多 k k k 次操作后,序列 a a a 中所有数的最小可能总和。
输入格式
每个测试包含多个测试用例。第一行包含测试用例数量 t t t( 1 ≤ t ≤ 1 0 4 1 \le t \le 10^4 1≤t≤104)。接下来是测试用例描述。
每个测试用例的第一行包含三个整数 n , m , k n, m, k n,m,k( 1 ≤ n ≤ 1 0 5 1 \leq n \leq 10^5 1≤n≤105, 1 ≤ m ≤ 10 1 \leq m \leq 10 1≤m≤10, 0 ≤ k ≤ n m 0 \leq k \leq nm 0≤k≤nm)—— 分别表示 a a a 的长度、魔法类型的数量和最大操作次数。
第二行包含 n n n 个整数 a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,…,an( 0 ≤ a i < 2 30 0 \leq a_i < 2^{30} 0≤ai<230)。
第三行包含 m m m 个整数 b 1 , b 2 , … , b m b_1, b_2, \ldots, b_m b1,b2,…,bm( 0 ≤ b i < 2 30 0 \leq b_i < 2^{30} 0≤bi<230)。
保证所有测试用例的 n n n 之和不超过 1 0 5 10^5 105。
输出格式
对于每个测试用例,输出一个整数 —— 在执行最多 k k k 次操作后,序列 a a a 中所有数的最小可能总和。
输入输出样例 #1
输入 #1
5
1 3 2
7
5 6 3
2 3 2
5 6
5 6 3
10 2 5
3 1 4 1 5 9 2 6 5 3
7 8
5 1 0
1073741823 1073741823 1073741823 1073741823 1073741823
1073741823
1 1 0
0
0
输出 #1
1
3
11
5368709115
0
说明 / 提示
第一个测试用例中,一种可能的操作方式为:
- 将 a 1 a_1 a1 更新为 a 1 & b 1 a_1\ \&\ b_1 a1 & b1,序列变为 [ 5 ] [5] [5]。
- 将 a 1 a_1 a1 更新为 a 1 & b 3 a_1\ \&\ b_3 a1 & b3,序列变为 [ 1 ] [1] [1]。
第二个测试用例中,一种可能的操作方式为:
- 将 a 1 a_1 a1 更新为 a 1 & b 3 a_1\ \&\ b_3 a1 & b3,序列变为 [ 1 , 6 ] [1, 6] [1,6]。
- 将 a 2 a_2 a2 更新为 a 2 & b 3 a_2\ \&\ b_3 a2 & b3,序列变为 [ 1 , 2 ] [1, 2] [1,2]。
翻译由 DeepSeek R1 完成
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int n, m, k;
std::cin >> n >> m >> k;
std::vector<i64> a(n + 1), b(m + 1);
std::vector<std::vector<i64>> num(n + 1, std::vector<i64>(m + 1, 1e18));
std::vector<i64> val(1 << m), res(n * m + 1);
i64 ans = 0;
for (int i = 1; i <= n; i++) {
std::cin >> a[i];
num[i][0] = a[i];
}
for (int i = 1; i <= m; i++) { std::cin >> b[i]; }
for (int i = 0; i < (1 << m); i++) {
val[i] = (1ll << 31) - 1;
for (int j = 1; j <= m; j++) {
if (i & (1 << (j - 1))) {
val[i] &= b[j];
}
}
}
for (int i = 1; i <= n; i++) {
for (int j = 0; j < (1 << m); j++) {
num[i][__builtin_popcount(j)] = std::min(num[i][__builtin_popcount(j)], val[j] & a[i]);
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) { res[(i - 1) * m + j] = num[i][j] - num[i][j - 1]; }
}
std::sort(res.begin() + 1, res.begin() + n * m + 1);
for (int i = 1; i <= n; i++) { ans += a[i]; }
for (int i = 1; i <= k; i++) { ans += res[i]; }
std::cout << ans << std::endl;
}
int main() {
#ifdef qmwneb
assert(freopen(".in.txt", "r", stdin));
assert(freopen(".out.txt", "w", stdout));
#endif
int t = 1;
std::cin >> t;
while (t--) { solve(); }
return 0;
}