专栏文章
题解:P13552 鱼类考古学
P13552题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miodw3jg
- 此快照首次捕获于
- 2025/12/02 17:36 3 个月前
- 此快照最后确认于
- 2025/12/02 17:36 3 个月前
总结:位运算最优化问题考虑按位贪心。
P13552 鱼类考古学
因为 ,因此我们一定是先 再 。
因此问题转化为,将全集分成 个集合(不是题目中的 ),使得每个集合权值总和最大,一个集合的权值定义为所有元素按位与。
赛时卡这了,没想到按位贪心。
从高位往低位考虑,发现按位贪心是对的,即,这一位在满足更高位限制的前提下,尽量产生最多 ,一定是最优的。证明如下:
-
假设考虑的是第 位,当前位每个 贡献为 ,定义一个集合的价值为 表示该集合权值的第 位是 ,。
-
设有 个价值为 的集合(A 类集合),有 个价值为 且有 的集合(B 类集合),有 个价值为 但只有 的集合(C)类集合。
-
如果 ,可以把任意一个 B 类集合中的 构成新的 A 类集合,剩余的 和任意一个 C 类集合合并。由于这个过程只涉及两个集合之间的元素转移,那么减少的贡献一定 ,而增加的贡献 ,因此答案变大。
-
如果存在一个 A 类集合 ,,且 ,那么可以把 拆分成两个 A 类集合,并把 C 类集合任意两个合并。显然拆分集合不会减少贡献,合并集合时减少的贡献也 ,因此答案增大。
-
因此,根据这样不断调整,答案一定不会变小,而调整的结果等价于贪心地使这一位产生的 尽量多。
考虑如何实现,首先枚举位,然后维护 表示当前需要分成多少个集合。如果 大于 的数量,直接把每个 单独分成一组,然后考虑 如何分组,递归到子问题;否则, 肯定会全部在一个组,那么直接把 全部缩成一个数,递归到子问题。
Code
CPP#include <bits/stdc++.h>
using namespace std;
using LL = long long;
using UI = unsigned int;
using ULL = unsigned long long;
using DB = double;
using LDB = long double;
using PII = pair<int, int>;
using PLL = pair<LL, LL>;
#define CP(x) complex<x>
#define fst first
#define snd second
#define popcnt(i) __builtin_popcount(i)
const int N = 1e6 + 5;
int n, k;
LL a[N];
void solve() {
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
LL ans = 0;
int m = n;
for (int i = 29; i >= 0; i--) {
int cnt = 0;
for (int j = 1; j <= m; j++) {
cnt += ((a[j] >> i) & 1);
}
if (k > cnt) {
n = 0;
for (int j = 1; j <= m; j++) {
if ((a[j] >> i) & 1) {
ans += a[j];
} else {
a[++n] = a[j];
}
}
k -= cnt;
m = n;
} else {
n = 0;
LL sum = -1;
for (int j = 1; j <= m; j++) {
if ((a[j] >> i) & 1) {
a[++n] = a[j];
} else {
if (sum == -1) sum = a[j];
else sum &= a[j];
}
}
if (sum != -1) {
a[++n] = sum;
}
m = n;
}
}
for (int i = 1; i < k; i++) ans += a[i];
LL sum = -1;
for (int i = k; i <= m; i++) {
if (sum == -1) sum = a[i];
else sum &= a[i];
}
ans += sum;
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int T = 1;
cin >> T;
while (T--) solve();
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...