# [CodeForce] Maximum Subsequence

Problem Statement

1. N is up to 35, so trying all possible subsequences is too slow (2^35). We can apply the meet in the middle technique and divide A into two equal halves and compute all possible subsequences' sum modulo by M. This takes O(2^17) for each half of A, call the results as S1 and S2.

2. Then for each value V in S1, we have 2 options: 1. take V and does not take anything from S2; 2. take V and find the max W in S2 such that V + W <= M - 1. The answer is the max of both options for all V in S1.

3. To speed up the search in option 2, we can either sort S2 then perform binary search or store values of S2 in a sorted set.

    static void solve(int testCnt)
{
for (int testNumber = 0; testNumber < testCnt; testNumber++) {
int n = in.nextInt(), m = in.nextInt();
int[] a = in.nextIntArrayPrimitive(n);
if(n == 1) out.println(a[0] % m);
else {
int[] x1 = Arrays.copyOfRange(a, 0, n / 2);
int[] x2 = Arrays.copyOfRange(a, n / 2, n);
TreeSet<Integer> ts1 = compute(x1, m);
TreeSet<Integer> ts2 = compute(x2, m);
int ans = 0;
for(int v : ts1) {
ans = Math.max(ans, v);
ans = Math.max(ans, v + ts2.floor(m - 1 - v));
}
out.println(ans);
}
}
out.close();
}

static TreeSet<Integer> compute(int[] x, int m) {
TreeSet<Integer> ts = new TreeSet<>();
for(int i = 0; i < (1 << x.length); i++) {
long sum = 0;
for(int j = 0; j < x.length; j++) {
if((i & (1 << j)) != 0) {
sum += x[j];
}
}
}