您的位置:首页 > 产品设计 > UI/UE

Codeforces 888E - Maximum Subsequence 折半枚举

2018-01-15 21:37 211 查看
888E -
Maximum Subsequence

题意:

给出了N个数和M,要在N个数中任意找出k个数,令这k个数的和mod M的值最大。(N<=35,M<=1e9)

分析:

用到了 meet-in-the-middle 的思想,能极大的优化
DFS 的暴力。数字的个数N最大只有35。但是直接暴力需要2^35显然不可以,我们可以分别暴力

左右n/2个数,丢到两个set中,遍历第一个set,再对第二个进行二分查找。这样复杂度就从O(2^n)降到O(log(N/2)*2^(N/2))

在二分过程中,如何取小于等于一个数的数呢(lower_bound or upper_bound都无法完成这中操作)。这里看到别人的做法大有收益,

就是首先将标等于upper_bound(),这样就取到了一个大于所求数的数,再将标自减(例:it--)就可以取到小于等于所求值的最大值了。

#include<bits/stdc++.h>
using namespace std;
const int MAX_N = 1e3 + 9;
set<int> st[2];
int vec[MAX_N];
int N,M,T;
void dfs(int val,int l,int r)
{
if(l == r)
{
st[r == N].insert(val);
return;
}
dfs((val+vec[l])%M,l+1,r);
dfs(val,l+1,r);
}
int main()
{
while(cin>>N>>M)
{
st[0].clear(); st[1].clear();
for(int i=0;i<N;i++)
{
cin>>vec[i];
vec[i] = vec[i]%M;
}
dfs(0,0,N/2);
dfs(0,N/2,N);
set<int>::iterator it,pos;
int ans = 0;
for(it = st[0].begin();it!=st[0].end();it++)
{
int t = *it;
int x = M - t - 1;
pos= st[1].upper_bound(x); //这里找到大于所求的数后将标向后移,恰好是小于等于所求数的标!
pos--;
ans = max(*pos+t,ans);
}
cout<<ans<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: