0
点赞
收藏
分享

微信扫一扫

E. Maximum Subsequence(中途相遇法)

那小那小 2022-03-13 阅读 31


补牛客多校的这道题:https://ac.nowcoder.com/acm/contest/882/F 中途相遇做法补自闭了(算贡献那里极其复杂,其实有更好的方法),于是找到了下面这个简单的了。

【题目】

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given an array ​a​ consisting of ​n​ integers, and additionally an integer ​m​. You have to choose some sequence of indices ​b​1, ​b​2, ..., ​bk​ (1 ≤ ​b​1 < ​b​2 < ... < ​bk​ ≤ ​n​) in such a way that the value of E. Maximum Subsequence(中途相遇法)_取模 is maximized. Chosen sequence can be empty.

Print the maximum possible value of E. Maximum Subsequence(中途相遇法)_取模.

Input

The first line contains two integers ​n​ and ​m​ (1 ≤ ​n​ ≤ 35, 1 ≤ ​m​ ≤ 109).

The second line contains ​n​ integers ​a​1, ​a​2, ..., ​an​ (1 ≤ ​ai​ ≤ 109).

Output

Print the maximum possible value of E. Maximum Subsequence(中途相遇法)_取模.

Examples

input

Copy

4 4
5 2 4 1

output

Copy

3

input

Copy

3 20
199 41 299

output

Copy

19

Note

In the first example you can choose a sequence ​b​ = {1, 2}, so the sum E. Maximum Subsequence(中途相遇法)_javascript_04 is equal to 7 (and that's 3 after taking it modulo 4).

In the second example you can choose a sequence ​b​ = {3}.

【题意】 

给n个数,让你任意选取几个数使得他们的和模m下是最大的。

【题解】

(感觉看到n<=35的第一反应已经是折半搜索了hhh)

显然可以先搜出前n/2个数和后面剩的数可以得到的所有子集(包括空集)的结果(对m取模后)。

然后答案肯定就是从前面选一个子集,后面再选一个子集,把两个拼起来。

假设我们在前n/2中选的子集的权值是s,那么怎么在后面的数中找最优子集呢?

假设我们在后面的数中找的子集的权值是p,那么有两种情况:

1.s+p<m

2.m<=s+p<2*m

对于第一种情况,我们找到<m-s的最大的p即可;

对于第二种情况,我们找到最大的p即可(肯定得减掉一个m,所以p肯定是越大越好)

经过认真分析,发现第二种情况是不存在的。

加上也不会错

【代码】

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6;
ll a[N],b[N],c[N];
int n;
ll m;
int cnt1,cnt2;
void dfs(int id,ll sum,int ty)
{
sum%=m;
if(ty==1&&id==n/2+1)
{

a[++cnt1]=sum;
return ;
}
else if(ty==2&&id==n+1)
{
b[++cnt2]=sum;
return ;
}
dfs(id+1,sum+c[id],ty);
dfs(id+1,sum,ty);
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;++i) {
scanf("%d",&c[i]);
}
dfs(1,0,1);
dfs(n/2+1,0,2);
ll ans=0;
sort(b+1,b+1+cnt2);
for(int i=1;i<=cnt1;++i)
{
int id=lower_bound(b+1,b+1+cnt2,m-a[i])-b;
--id;
ans=max(ans,a[i]+b[id]);
}
cout<<ans<<endl;
return 0;
}



举报

相关推荐

0 条评论