E. Maximum Subsequence
题意:
第一行输入
n
(
35
)
,
m
(
1
e
9
)
n(35),m(1e9)
n(35),m(1e9);
第二行
a
1
,
a
2
,
…
,
a
n
(
1
e
9
)
a_1,a_2,\dots,a_n(1e9)
a1,a2,…,an(1e9)。
问:在数组中选择几个数使
∑
a
i
m
o
d
m
\sum a_i\mod m
∑aimodm最大。
题解:
首先想到的是直接暴力搜索,这样复杂度是
O
(
2
n
)
O(2^n)
O(2n),显然是超时的。
这里用到一种叫meet-in-the-middle的搜索优化。
1、将
n
n
n分为两部分
n
/
2
n/2
n/2;
2、对这两部分分别进行搜索,并把搜索的结果分别插入
s
e
t
set
set中;
3、最后循环第一部分,二分找第二部分中使答案最大的值。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n,m,a[40];
vector<int>b[2];
set<int>c[2];
void dfs(vector<int>a,int x,int y,set<int> &b){
if(x==a.size()){
b.insert(y);
return;
}
dfs(a,x+1,y,b);
dfs(a,x+1,(y+a[x])%m,b);
}
int mx;
int main(){
//freopen("tt.in","r",stdin),freopen("tt.out","w",stdout);
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i],b[i>=n/2].push_back(a[i]);
dfs(b[0],0,0,c[0]);dfs(b[1],0,0,c[1]);
for(auto i:c[0])mx=max(mx,i+*(--c[1].upper_bound(m-1-i)));
cout<<mx<<endl;
return 0;
}