Go: ///
// File:  0529.go
// Author: ymiyamoto
//
// Created on Wed Feb 28 20:39:28 2018
//
package main

import (
	"fmt"
	"sort"
)

func max(n, m int64) int64 {
	if n < m {
		return m
	} else {
		return n
	}
}

func main() {
	for {
		var N int
		var M int64
		fmt.Scan(&N, &M)
		if N == 0 && M == 0 {
			break
		}

		arr := make([]int64, N+1)
		for i := 1; i <= N; i++ {
			fmt.Scan(&arr[i])
		}
		sort.Slice(arr, func(i, j int) bool { return arr[i] < arr[j] })

		sums := make([]int64, len(arr)*len(arr))
		for i := 0; i < len(arr); i++ {
			for j := 0; j < len(arr); j++ {
				sums[i*len(arr)+j] = arr[i] + arr[j]
			}
		}

		sort.Slice(sums, func(i, j int) bool { return sums[i] < sums[j] })
		var m int64 = 0
		for _, val := range sums {
			rem := M - val
			if rem >= 0 {
				index := sort.Search(len(sums), func(i int) bool { return sums[i] > rem }) - 1
				if index >= 0 {
					m = max(m, val+sums[index])
				}
			}
		}
		fmt.Println(m)
	}
}

C++: import java.util.Arrays;
import java.util.Scanner;


public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		
		while(true){
			int n = sc.nextInt();
			int m = sc.nextInt();
			
			if(n == 0 && m == 0){
				break;
			}
			int[] input = new int[n];
			
			for(int i = 0; i < n ; i++){
				input[i] = sc.nextInt();
			}
			
			System.out.println(solve(input, m));
		}
	}
	
	//半分全列挙で解きたい
	static long solve(int[] array, int limit){
		int n = array.length + 1;
		int[] copyArray = new int[n];
		//0を追加した配列を作る
		for(int i = 0 ; i < n - 1; i++){
			copyArray[i] = array[i];
		}
		
		//2回投げたときに有り得る得点
		long[] twoTimes = new long[n*n];
		
		int index = 0;
		for(int i = 0; i < n; i++){
			for(int j = 0; j < n; j++){
				twoTimes[index++] = copyArray[i] + copyArray[j];
			}
		}
		
		Arrays.sort(twoTimes);
		//debug
//		for(int i = 0; i < twoTimes.length; i++){
//			System.out.println(twoTimes[i]);
//		}
		
		long result = 0;
		
		for(int i = 0; i < twoTimes.length ; i++){
			//そもそも2回だけで済む場合
			if(twoTimes[i] == limit){
				System.out.println("JUST");
				return twoTimes[i];
			}
			
			//既にオーバーしている場合も論外
			else if (twoTimes[i] > limit){
//				System.out.println("OVER i = "+i+" "+twoTimes[i]);
				break;
			}
			
			//わざと少し下を狙う
			int tmpIndex = Arrays.binarySearch(twoTimes, limit - twoTimes[i] - 1);
			
			if(tmpIndex < 0){
				tmpIndex++;
				tmpIndex *= -1;
				tmpIndex--;
			}
			
			if(tmpIndex >= twoTimes.length){
				tmpIndex = twoTimes.length - 1;
			}
			
			
			for(int j = Math.max(tmpIndex, 0); j < twoTimes.length; j++){
//				if(twoTimes[i] + twoTimes[j] > limit){
//					break;
//				}
//				System.out.println("j = "+j+" "+twoTimes[i] + " "+twoTimes[j]);
				if(twoTimes[i] + twoTimes[j] > limit){
					break;
				}
				result = Math.max(result, twoTimes[i] + twoTimes[j]);
			}
		}
		return result;
	}

}

C++: #include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

typedef long long ll;
typedef pair<ll, ll> P;

#define MOD 1000000007
#define REP(i, N) for (int i = 0; i < N; ++i)
#define REP1(i, N) for (int i = 1; i <= N; ++i)
#define RREP(i, N) for (int i = N - 1; i >= 0; --i)
#define ALL(a) a.begin(), a.end()

int main() {
  int n;
  ll m;
  while (cin >> n >> m && n && m) {
    vector<ll> a, b, c, d;
    a.push_back(0);
    b.push_back(0);
    c.push_back(0);
    d.push_back(0);
    REP(i, n) {
      ll p;
      cin >> p;
      a.push_back(p);
      b.push_back(p);
      c.push_back(p);
      d.push_back(p);
    }
    a.push_back(1e9);
    b.push_back(1e9);
    c.push_back(1e9);
    d.push_back(1e9);
    vector<ll> ab;
    REP(i, a.size()) REP(j, b.size()) ab.push_back(a[i] + b[j]);
    sort(ALL(ab));
    ll ans = -1e18;
    REP(i, c.size()) REP(j, d.size()) {
      ll k = m - (c[i] + d[j]);
      if (k < 0) continue;
      int ok = 0, ng = ab.size() - 1;
      while (1 < abs(ok - ng)) {
        int mid = (ok + ng) / 2;
        if (ab[mid] <= k)
          ok = mid;
        else
          ng = mid;
      }
      ans = max(ans, c[i] + d[j] + ab[ok]);
    }
    cout << ans << endl;
  }
  return 0;
}

C++: #include <cstdio>
#include <algorithm>
#pragma warning(disable : 4996)
using namespace std;
int n, m, c[1009], s[510009], t[510009], cnt[1027], sum[1027];
int main() {
	while (scanf("%d%d", &n, &m), n) {
		for (int i = 1; i <= n; i++) scanf("%d", &c[i]);
		sort(c, c + n);
		int b = 0;
		for (int i = 0; i <= n; i++) {
			for (int j = i; j <= n && c[i] + c[j] <= m; j++) {
				s[b++] = c[i] + c[j];
			}
		}
		for (int i = 0; i < 30; i += 10) {
			fill(cnt, cnt + 1024, 0); sum[0] = 0;
			for (int j = 0; j < b; j++) cnt[(s[j] >> i) & 1023]++;
			for (int j = 0; j < 1024; j++) sum[j + 1] = sum[j] + cnt[j];
			for (int j = 0; j < b; j++) t[sum[(s[j] >> i) & 1023]++] = s[j];
			for (int j = 0; j < b; j++) s[j] = t[j];
		}
		int r = b - 1, ret = 0;
		for (int i = 0; i < b && i <= r; i++) {
			while (r > 0 && s[i] + s[r] > m) r--;
			ret = max(ret, s[i] + s[r]);
		}
		printf("%d\n", ret);
	}
	return 0;
}

C++: #include <iostream>
#include <cstdio>
#include <algorithm>

#define MAX_N (1000)
#define MAX_M (2 * 1e8)

using namespace std;

int field[MAX_N + 1];
int fld[(MAX_N + 1) * (MAX_N + 1)];

int N,M;

int ans;

int bin_search(int tar,int *s,int *e){
	int result;
	int width = e - s;
	while(true){
		width = e - s;
		if(width <= 1){
			result = *s;
			break;
		}

		if(*(s + (width / 2)) <= tar){
			s = s + (width / 2);
		}
		else{
			e = s + (width / 2);
		}
	}
	
	return result;
}

void solve(){
	for(int i = 0;i <= N;i++){
		for(int j = 0;j <= N;j++){
			fld[(N + 1) * i + j] = field[i] + field[j];
		}
	}

	sort(fld,fld + (N + 1) * (N + 1));

	int rest;
	int sample;
	for(int i = 0;i <= N;i++){
		for(int j = 0;j <= N;j++){
			rest = M - (field[i] + field[j]);
			if(rest < 0) break;
			sample = bin_search(rest,fld,fld + (N + 1) * (N + 1));
			ans = max(ans,field[i] + field[j] + sample);
		}
	}

	return ;
}

int main(){

	while(true){
		scanf("%d%d",&N,&M);
		if(N == 0 && M == 0) break;
		for(int i = 1;i <= N;i++){	//fiest element is 0;
			scanf("%d",field + i);
		}

		solve();

		printf("%d\n",ans);

	}

	return 0;
}

C++: #include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

int main() {
	int n;
	long long int m;
	while (cin >> n >> m) {
		if (n == 0 && m == 0) {
			break;
		}
		long long int b;
		vector<long long int> ss;
		ss.push_back(0);
		for (int i = 0; i < n; i++) {
			cin >> b;
			if (b <= m) {
				ss.push_back(b);
			}
		}
		vector<long long int> ss2;
		for (long long int i = 0; i < ss.size(); i++) {
			ss2.push_back(ss[i]);
			for (long long int j = i; j < ss.size(); j++) {
				if (ss[i]+ss[j] <= m) {
					ss2.push_back(ss[i]+ss[j]);
				}
			}
		}
		sort(ss2.begin(), ss2.end());
		/*for (long long int i = 0; i < ss2.size(); i++) {
			cout << ss2[i] << endl;
		}*/
		long long int MAX = 0;
		long long int sz = ss2.size();
		for (long long int j = 0; j < sz; j++) {
			long long int a = m;
			for (long long int i = 0; i < 2; i++) {
				vector<long long int>::iterator ite = upper_bound(ss2.begin(), ss2.end(), a);
				if (ite != ss.begin()) {
					ite--;
					a -= *(ite);
				}
			}
			vector<long long int>::iterator ite2 = ss2.end();
			ss2.erase(ite2-1);
			MAX = max(MAX, m-a);
		}
		cout << MAX << endl;
	}
	return 0;
}