CF888E Maximum Subsequence 题解
首先看完本题,最直接的想法就是——爆搜!
但是, 让我们望而却步,因此我们需要考虑一定的优化。
而本题的优化是十分经典的 折半搜索 (Meet in middle) 算法。
折半搜索的主要思路就是:将序列裂成两半搜索,然后合并答案。
对于这道题,我们首先对 做一次暴力搜索, 做一次暴力搜索,统计的和存在 里面,其中不要忘记取模。
但是这样还是没有用啊?此时就要请出另一利器:尺取法。
首先对 排个序,然后指定 。
由于此时 中每个数都在 范围内。因此我们只需要考虑 的结果即可。为什么不需要考虑大于 的?因为最大值 ,此时对于大于 的和而言, 一定是最优解,因此不需要考虑。
想清楚后代码就很简单了。
代码:
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 40 + 10;
int n, m, a[MAXN], ans1[1 << 20], ans2[1 << 20], mid, cnt1, cnt2, ans;
int read()
{
int sum = 0, fh = 1; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') fh = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {sum = (sum << 3) + (sum << 1) + (ch ^ 48); ch = getchar();}
return sum * fh;
}
void dfs1(int k, int sum)
{
if(k == mid + 1) {ans1[++cnt1] = sum; return ;}
dfs1(k + 1, sum); dfs1(k + 1, (sum + a[k]) % m);
}
void dfs2(int k, int sum)
{
if(k == n + 1) {ans2[++cnt2] = sum; return ;}
dfs2(k + 1, sum); dfs2(k + 1, (sum + a[k]) % m);
}
int main()
{
n = read(); m = read();mid = n >> 1;
for(int i = 1; i <= n; ++i) a[i] = read();
dfs1(1, 0); dfs2(mid + 1, 0);
sort(ans1 + 1, ans1 + cnt1 + 1); sort(ans2 + 1, ans2 + cnt2 + 1);
int pos1 = 1, pos2 = cnt2;
while(pos1 <= cnt1 && pos2 >= 1)
{
while(ans1[pos1] + ans2[pos2] >= m) pos2--;
ans = max(ans, ans1[pos1] + ans2[pos2]); pos1++;
}
printf("%d\n", max(ans, (ans1[cnt1] + ans2[cnt2]) % m));
return 0;
}
标签:
搜索
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具