Maximum Subsequence / CodeForces - 888E

img

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(看右图) .

Sample Input 1

 4 4
 5 2 4 1

Sample Output

 3

Sample Input 1

 3 20
 199 41 299

Sample Output

 19

Note

img

题意

给n个数,求个区间,使其的和取余m最大,求最大余数

题解

折半枚举

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 18;

int n, m, t = 1, ret;
int a[2 * N], b[1 << N];

int find(int x){//二分
    int left = 0, right = t - 1, best = 1 << N;
    while (left <= right){
        int mid = (left + right) / 2;
        if(b[mid] == x){
            return x;
        }
        if(b[mid] > x){
            right = mid - 1;
        }else{
        //当b[mid]<x时才更新best,是因为宁可比x小也不能比其大,这样余数最大化
            best = b[mid];
            left = mid + 1;
        }
    }
    if(best == 1 << N){//如果没有比x小的数
        return b[t - 1];//返回最大的余数
    }
    return best;
}

int main(){
    scanf("%d%d", &n, &m);
    for(int i = 0; i < n; i++){
        scanf("%d", &a[i]);
        a[i] %= m;//每个都这样保存,嗯
    }
    int half = n / 2;//前一半
    for(int mask = 0; mask < (1 << half); mask++){//枚举每一种状态
        int tmp = 0;
        for(int i = 0; i < half; i++){//每个点搜一遍
            if(mask & (1 << i)){//如果i点被选中
                tmp = (tmp + a[i]) % m;//把选中的点加上
            }
        }
        b[t++] = tmp;//第t个状态的的余数
    }
    sort(b, b + t);//排个序
    half = n - n / 2;//后一半
    for(int mask = 0; mask < (1 << half); mask++){//同上
        int tmp = 0;
        for(int i = 0; i < half; i++){//同上
            if(mask & (1 << i)){//同上
                tmp = (tmp + a[i + n / 2]) % m;//同上
            }
        }
        int x = find(m - tmp - 1);
        //为了余数最大化,找一个数最接近(m - tmp - 1)稍加证明可知这样余数最大
        ret = max(ret, (x + tmp) % m);//找最大余数
    }
    printf("%d\n", ret);
    return 0;
}
PS
为什么find()函数中要写:
if(best == 1 << N){//如果没有比x小的数
     return b[t];//返回最大的余数
}
举个栗子
设一个数6, x = 4
当前只有余数3,4,5 3种
经计算发现,此时只有选择最大的余数最后的余数才能最大
posted @ 2020-02-29 20:36  LT-Y  阅读(101)  评论(0)    收藏  举报