[CodeForce] Maximum Subsequence
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]; } } ts.add((int)(sum % m)); } return ts; }