Maximum Subsequence CodeForces

来源:互联网 发布:cf东东数据一键刷枪 编辑:程序博客网 时间:2024/05/18 00:53

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 0x3f3f3f3fusing 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;}
阅读全文
0 0