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 .
Input
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).
Output
Print the maximum possible value of .
Example
Input
4 4
5 2 4 1
Output
3
Input
3 20
199 41 299
Output
19
Note
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}.
这题的数据范围是35,去枚举可能是不可能的,但是如果n为17或者18,也是可以的,所以这里用状压,把数据先分成两部分,然后把其中一部分用状压枚举所有可能(记得取模),然后排序去重,然后去枚举另一半的组合也是状压去枚举(v1),然后在左边去二分查找值(v2),应该这样去找,使得v1+v2最大,当然最大只能为m-1。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
int a[262148];
int p[40];
int findd(int limit,int num)//返回的是最接近num的值,但是不会大于num
{
int l=0,r=limit-1;
if(a[r]<=num)
return a[r];
while(l<=r)
{
int mid=(l+r)>>1;
if(a[mid]==num)
return a[mid];
if(a[mid]>num)
r=mid-1;
else
l=mid+1;
}
return a[l-1];
}
int main()
{
int n,m;
int k1=0;
int k2=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",p+i),p[i]%=m;
int limit=n/2;
for(int i=0;i<(1<<limit);i++)
{
int t=0;
for(int j=1;j<=limit;j++)
if(i&(1<<(j-1)))
t=(t+p[j])%m;
a[k1++]=t;
}
sort(a,a+k1);
int num=unique(a,a+k1)-a;
int left=n-limit;
int ans=0;
for(int i=0;i<(1<<left);i++)//枚举
{
int temp=0;
for(int j=1;j<=left;j++)
if(i&(1<<(j-1)))
temp=(temp+p[limit+j])%m;
int now=m-1-temp;
int get=findd(num,now);
//cout<<temp<<" "<<get<<endl;
ans=max(ans,get+temp);
if(ans==m-1)//如果最大就没必要举继续找了
break;
}
printf("%d\n",ans);
return 0;
}