Codeforces 888E - Maximum Subsequence
888E - Maximum Subsequence
题意
给出一些数字,现在选择 \(k\) 个不同的下标对应的数字,问它们的和模 \(m\) 最大为多少?
分析
用到了 meet-in-the-middle 的思想,能极大的优化 DFS 的暴力。
数字的个数 \(n\) 只有 \(35\),但直接暴力 \(2^{35}\) 显然不行。
我们可以分别暴力左右 \(\frac{n}{2}\) 个数,分别丢到两个 \(set\) 中,遍历第一个 \(set\) ,二分查找第二个 \(set\) 。
复杂度:\(O(2^{\frac{n}{2}}log(2^{\frac{n}{2}}))\) 也就是 \(O(\frac{n}{2}*2^{\frac{n}{2}})\)。
code
#include<bits/stdc++.h>
using namespace std;
int n, m, a[44];
set<int> st[2];
void dfs(int s, int l, int r) {
if(l == r) {
st[r == n].insert(s);
return;
}
dfs((s + a[l]) % m, l + 1, r);
dfs(s, l + 1, r);
}
int main() {
cin >> n >> m;
for(int i = 0; i < n; i++) cin >> a[i];
dfs(0, 0, n / 2);
dfs(0, n / 2, n);
st[0].insert(0);
st[1].insert(0);
int ans = 0;
for(int i : st[0]) {
int x = m - i - 1;
auto it = st[1].upper_bound(x);
it--;
ans = max(ans, *it + i);
}
cout << ans << endl;
return 0;
}