CF2061E Kevin and And

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 1in)和 j j j 1 ≤ j ≤ m 1 \leq j \leq m 1jm),然后将 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 1t104)。接下来是测试用例描述。

每个测试用例的第一行包含三个整数 n , m , k n, m, k n,m,k 1 ≤ n ≤ 1 0 5 1 \leq n \leq 10^5 1n105 1 ≤ m ≤ 10 1 \leq m \leq 10 1m10 0 ≤ k ≤ n m 0 \leq k \leq nm 0knm)—— 分别表示 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} 0ai<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} 0bi<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

说明 / 提示

第一个测试用例中,一种可能的操作方式为:

  1. a 1 a_1 a1 更新为 a 1   &   b 1 a_1\ \&\ b_1 a1 & b1,序列变为 [ 5 ] [5] [5]
  2. a 1 a_1 a1 更新为 a 1   &   b 3 a_1\ \&\ b_3 a1 & b3,序列变为 [ 1 ] [1] [1]

第二个测试用例中,一种可能的操作方式为:

  1. a 1 a_1 a1 更新为 a 1   &   b 3 a_1\ \&\ b_3 a1 & b3,序列变为 [ 1 , 6 ] [1, 6] [1,6]
  2. 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qmwneb946

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值