codeforces888e(折半枚举+二分搜索)

来源:互联网 发布:linux系统iso镜像下载 编辑:程序博客网 时间:2024/04/29 06:11

E. Maximum Subsequence
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 indicesb1, 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 ≤ 351 ≤ m ≤ 109).

The second line contains n integers a1a2, ..., an (1 ≤ ai ≤ 109).

Output

Print the maximum possible value of .

Examples
input
4 45 2 4 1
output
3
input
3 20199 41 299
output
19
题意:给一个数组,选择任意几个数,求它们和m取模的最大值。

思路:折半枚举大法好,因为数组最长为35,所以分别对数组前半和后半的和对m取模的情况进行枚举,然后对一个排序后二分搜索模m最大值,复杂度为2^(n/2)logn。

#include<iostream>#include<stdio.h>#include<string.h>#include<vector>#include<algorithm>using namespace std;int a[40];int data1[300005];int data2[300005];int cnt1;int cnt2;int n,m;void dfs1(int sum,int i,int n){if(i>(n-1)/2){data1[cnt1++]=sum;return;}dfs1((sum+a[i])%m,i+1,n);dfs1(sum%m,i+1,n);}void dfs2(int sum,int i,int n){if(i>=n){data2[cnt2++]=sum;return;}dfs2((sum+a[i])%m,i+1,n);dfs2(sum%m,i+1,n);}int main(){while(~scanf("%d%d",&n,&m)){for(int i=0;i<n;i++)scanf("%d",&a[i]);cnt1=0;cnt2=0;dfs1(0,0,n);dfs2(0,(n-1)/2+1,n);sort(data2,data2+cnt2);int ans=0;for(int i=0;i<cnt1;i++){int x = m-data1[i];int p1=lower_bound(data2,data2+cnt2,x)-data2;if(p1>0){ans=max(ans,(data1[i]+data2[p1-1])%m);}ans=max(ans,(data1[i]+data2[cnt2-1])%m);}printf("%d\n",ans);}}







原创粉丝点击