You are given an array a consisting of n integers,
and additionally an integer m. You have to choose some sequence of indices b1, b2, ..., bk (1 ≤ b1 < b2 < ... < bk ≤ n)
in such a way that the value of is
maximized. Chosen sequence can be empty.
Print the maximum possible value of .
The first line contains two integers n and m (1 ≤ n ≤ 35, 1 ≤ m ≤ 109).
The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 109).
Print the maximum possible value of .
4 4 5 2 4 1
3
3 20 199 41 299
19
In the first example you can choose a sequence b = {1, 2}, so the sum is
equal to 7 (and that's 3 after
taking it modulo 4).
In the second example you can choose a sequence b = {3}.
思路:2的35次方会超时,考虑折半搜索,前后分别枚举,最后二分取最大值即可。
# include <bits/stdc++.h>
# define pb push_back
# define mp make_pair
using namespace std;
typedef long long LL;
LL a[40], n, m;
set<LL>s, t;
void dfs(int cur, LL sum)
{
if(cur == n/2+1)
{
sum = sum%m;
s.insert(sum);
return;
}
dfs(cur+1, sum);
dfs(cur+1, sum+a[cur]);
}
void dfs2(int cur, LL sum)
{
if(cur == n+1)
{
sum = sum%m;
t.insert(sum);
return;
}
dfs2(cur+1, sum);
dfs2(cur+1,sum+a[cur]);
}
int main()
{
scanf("%lld%lld",&n,&m);
for(int i=1; i<=n; ++i) scanf("%lld",&a[i]);
dfs(1, 0);
dfs2(n/2+1, 0);
LL ans = 0;
for(auto it=s.begin(); it!=s.end(); ++it)
{
LL tmp = *it;
auto pos = t.lower_bound(m-tmp);
if(pos != t.begin())
{
--pos;
if(*pos + tmp <= m)
ans = max(ans, *pos + tmp);
}
}
printf("%lld\n",ans);
return 0;
}