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+j] = arr[i] + arr[j]
			}
		}
		sort.Slice(sums, func(i, j int) bool { return sums[i] < sums[j] })

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

C++: #include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

vector<long long> v,v2;

bool isOK(int index, int key){
  /*indexが条件を満たすかどうかを判定(今回はkeyよりおおきいか)*/
  if(v2[index]<=key) return true;
  else return false;
}

int binary_search(int key){
  int ng = (int)v2.size();
  int ok = -1;
  //okとngの初期値によって最大値だけでなく最小値も求められる.
  //ng=-1の時はkey以上の数値の最小値

  while(abs(ok - ng) > 1){
    int mid = (ok + ng) / 2;

    if(isOK(mid,key)) ok = mid;
    else ng = mid;
  }

  return ok;
}


int main(){
  long long n,m;
  while(cin >> n >> m){
    if(n==0)break;
    v.clear();
    v.resize(n+1);
    v[0]=0;
    long long i,j;
    for (i = 1; i < n+1; i++) {
      cin >> v[i];
    }
    v2.clear();
    v2.resize((n+1)*(n+2)/2);
    for(i=0;i<n+1;i++){
      for(j=i;j<n+1;j++){
        v2.emplace_back(v[i]+v[j]);
      }
    }
    sort(v2.begin(),v2.end());
    long long ret=0;
    for(i=0;i<v2.size();i++){
      if(v2[i]>m)break;
      int key=binary_search(m-v2[i]);
      if(key!=-1)ret=max(ret,v2[i]+v2[key]);
    }
    cout << ret << endl;
  }
  return 0;
}

C++: #include<iostream>
#include<set>
using namespace std;

int main(int argc, char *argv[]){
  int n, m;
  while(cin >> n >> m, n){
    int point[n + 1];
    point[0] = 0;
    set<int> a;
    for (int i = 1; i <= n; i++) {
      cin >> point[i];
    }
    for (int i = 0; i <= n; i++) {
      for (int j = 0; j <= n; j++) {
        a.insert(point[i] + point[j]);
      }
    }
    int ans = 0;
    for (set<int>::iterator ite = a.begin(); ite != a.end(); ite++) {
      ans = max(ans, *ite + *(--a.upper_bound(m - *ite)));
    }
    std::cout << ans << std::endl;
  }
  return 0;
}

C++: #include<iostream>
#include<set>
#include<vector>
using namespace std;
typedef unsigned int uint;
uint maxv;
void solve(uint now,uint m,uint *a,int n){
  int r=n-1,l=0,mid;
  while(l <=r){
    mid = (l+r)/2;
    if ( a[mid]+now>m)r=mid-1;
    else if ( a[mid]+now <m)l=mid+1;
    else break;

  }
  if ( now+a[mid]>maxv&& now+a[mid]<=m)maxv=now+a[mid];
}


main(){
  int n;
  uint m;
  while(scanf("%d%u",&n,&m) && n){
    uint one[n];
    uint two[n*n];
    int p=0;
    maxv=0;
    for(int i=0;i<n;i++)scanf("%d",&one[i]);
    for(int i=0;i<n;i++){
      if ( one[i]>maxv &&one[i] <=m)maxv=one[i];
      for(int j=i;j<n;j++){
	if ( one[i]+one[j]>m)continue;
	two[p++]=one[i]+one[j];
	if (two[p-1]>maxv&&two[p-1]<=m)maxv=two[p-1];
      }
    }
    sort(one,one+n);
    sort(two,two+p);
    for(int i=0;i<p;i++){
      if ( two[i]+one[0]>m)break;
      if ( two[i]+two[0]<=m)solve(two[i],m,two,p);
      if ( two[i]+one[0]<=m)solve(two[i],m,one,n);
    }
    printf("%u\n",maxv);
  }
  return false;
}

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

using namespace std;

int main()
{
	int N, M, D;

	while (true)
	{
		scanf("%d", &N);
		scanf("%d", &M);

		if (N == 0 && M == 0) { break; }

		vector<int> C; C.push_back(0);

		for (int i = 0; i < N; i++)
		{
			scanf("%d", &D);

			if (D <= M)
			{
				C.push_back(D);
			}
		}

		vector<int> r1, r;

		for (int i = 0; i < C.size(); i++)
		{
			for (int j = i; j < C.size(); j++)
			{
				if (C[i] + C[j] <= M)
				{
					r1.push_back(C[i] + C[j]);
				}
			}
		}

		sort(r1.begin(), r1.end());

		r.push_back(r1[0]);

		for (int i = 0; i < r1.size(); i++)
		{
			if (r1[i - 1] != r1[i])
			{
				r.push_back(r1[i]);
			}
		}

		int ret = 0;

		for (int i = 0; i < r.size(); i++)
		{
			int ptr = upper_bound(r.begin(), r.end(), M - r[i]) - r.begin() - 1;
			
			if (ptr >= 0)
			{
				ret = max(ret, r[i] + r[ptr]);
			}
		}

		printf("%d\n", ret);
	}

	return 0;
}

C++: // http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0529
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define REP(i, n) FOR(i, 0, n)
#define REPR(i, n) for (int i = n - 1; i >= 0; i--)
#define FOR(i, s, n) for (int i = (s), i##_len = (n); i < i##_len; ++i)
#define ALL(obj) (obj).begin(), (obj).end()
#define ALLR(obj) (obj).rbegin(), (obj).rend()
#define DIV(a, b) ((a - 1) / b + 1)

signed main() {
    int N, M;
    while (cin >> N >> M, N) {
        vector<int> P(N + 1);
        REP(i, N) { cin >> P[i]; }
        // ダーツ2回投げた組み合わせを作成し、それらの組み合わせを
        // 求めることでダーツ4回の組み合わせになる
        P[N] = 0;
        vector<int> v;
        REP(i, N + 1) REP(j, N + 1) { v.emplace_back(P[i] + P[j]); }
        sort(ALL(v));
        unique(ALL(v));
        int res = 0;
        for (auto &x : v) {
            if (x > M) {
                break;
            }
            res = max(res, x + *(lower_bound(ALL(v), M - x + 1) - 1));
        }
        cout << res << endl;
    }
}

C++: #include<bits/stdc++.h>
using namespace std;
int sum[1001*1001]={0};
int sum1[1001*1001]={0};
int main(void){
	int n,m;
	int i,j;
	int high,low,base,mid;
	int a[1001];
	int k,l;
	int MIN;
	int ans;
	int sgm;
	while(1){
		cin>>n>>m;
		if(n==0&&m==0)	break;
		for(i=0;i<n;i++){
			cin>>a[i];
		}
		a[n]=0;
		sort(a,a+n+1);
		//for(i=0;i<=n;i++)	 cout<<a[i]<<endl;cout<<endl;
		int flg;
		MIN=INT_MAX;
		ans=0;
		l=0;
		for(i=0;i<=n;i++){
			for(j=0;j<=n;j++){
				sum[l]=a[i]+a[j];
				l++;
			}
		}
		sort(sum,sum+l);
		//for(i=0;i<l;i++)	cout<<i+1<<" "<<sum[i]<<endl;
		k=0;
		for(i=0;i<l;i++){
			if(sum[i]!=sum[i+1]){
				sum1[k]=sum[i];
				k++;
			}
		}
		//for(i=0;i<k;i++)	cout<<i+1<<" "<<sum1[i]<<endl;
		for(i=0;i<k;i++){
			sgm=sum1[i];
			if(sgm<=m){
				base=m-sgm;
				high=k-1;
				low=0;
				flg=0;
				while(low<=high){
					mid=(high+low)/2;
					if(base<sum1[mid]){
						high=mid-1;
					}
					else if(base>sum1[mid]){
						low=mid+1;
					}
					else{
						flg=1;
						break;	
					}
				}
				if(flg==1){
					sgm+=base;
				}	
				else{
					sgm+=sum1[high];
				}
			}
			//cout<<"M="<<MIN<<" "<<"SA="<<m-sgm<<" "<<"SGM="<<sgm<<endl;
			if(MIN>m-sgm&&m>=sgm){
				MIN=m-sgm;
				ans=sgm;
				//cout<<"ans="<<ans<<endl;
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}