ARC100E Or Plus Max
位运算上的比大小问题通常都很难处理,因此一般都是先把这种条件转化。
考虑下面三个集合:
。 。- 这里
的意思,可以用以下四种等价角度理解: 。 是按位与的意思。- 同一个二进制位上,
的这一位小于等于 的这一位。 - 同一个二进制位上,
这一位为 ,则 这一位可以为 或 ; 这一位为 ,则 这一位只能为 。 的所有为 的二进制位数集,是 的所有为 的二进制位数集的子集。
- 这里
。
不难发现
不难发现
用语言说明这个转化的正确性:
为什么要这么转化?两个原因。
【原因一】
原先
而
当然一直还有一个二元制约关系是
【原因二】
不难发现
假设数对
因此考虑求
不难发现,我们只需要维护满足
而最大值和次大值与和一样,可以方便地合并。这题做完了。
/*
* @Author: crab-in-the-northeast
* @Date: 2023-04-17 10:20:23
* @Last Modified by: crab-in-the-northeast
* @Last Modified time: 2023-04-17 11:06:28
*/
#include <bits/stdc++.h>
inline int read() {
int x = 0;
bool f = true;
char ch = getchar();
for (; !isdigit(ch); ch = getchar())
if (ch == '-')
f = false;
for (; isdigit(ch); ch = getchar())
x = (x << 1) + (x << 3) + ch - '0';
return f ? x : (~(x - 1));
}
inline bool gmx(int &a, int b) {
return b > a ? a = b, true : false;
}
const int maxn = 19;
std :: vector <int> f[1 << maxn];
int main() {
int n = read();
for (int i = 0; i < (1 << n); ++i)
f[i].push_back(read());
for (int j = 0; j < n; ++j) {
for (int i = 0; i < (1 << n); ++i) {
if (i & (1 << j)) {
int lst = i ^ (1 << j);
for (int x : f[lst])
f[i].push_back(x);
std :: sort(f[i].begin(), f[i].end(), std :: greater <int> ());
while (f[i].size() > 2)
f[i].pop_back();
}
}
}
int ans = 0;
for (int K = 1; K < (1 << n); ++K) {
gmx(ans, f[K][0] + f[K][1]);
printf("%d\n", ans);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】