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;
}
posted @ 2017-11-11 21:19  ftae  阅读(666)  评论(0编辑  收藏  举报