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 <queue>
using namespace std;
const int MAX_M = 100000000;
int n, m, p[1000], save;
bool  dp[MAX_M];
queue <int> que;
int main() {#include <iostream>
#include <queue>
using namespace std;
const int MAX_M = 100000000;
int n, m, p[1000], save;
bool  dp[MAX_M+1];
queue <int> que;
int main() {
	while (cin >> n >> m){
		for (int i = 0; i<n; i++){
			cin >> p[i];
		}
		for(int i=0;i<m;i++){
			dp[i]=0;
		}
		dp[0] = 1;
		que.push(0);
		for (int i = 0; i<n; i++){
			dp[p[i]] = 1;
			que.push(p[i]);
		}
		for (int i = 1; i<4; i++){
			save=que.size();
			for (int k=0;k<save;k++){
				for (int j = 0; j < n; j++){
					if (que.front() + p[j] < m){
						dp[que.front() + p[j]] = 1;
						que.push(que.front() + p[j]);
					}
				}
				que.pop();
			}
		}
		for (int i = m - 1; i >= 0; i--){
			if (dp[i] != 0){
				cout << i << endl;
				break;
			}
		}
	}
	return 0;
}
	while (cin >> n >> m){
		for (int i = 0; i<n; i++){
			cin >> p[i];
		}
		for(int i=0;i<m;i++){
			dp[i]=0;
		}
		dp[0] = 1;
		que.push(0);
		for (int i = 0; i<n; i++){
			dp[p[i]] = 1;
			que.push(p[i]);
		}
		for (int i = 1; i<4; i++){
			save=que.size();
			for (int k=0;k<save;k++){
				for (int j = 0; j < n; j++){
					if (que.front() + p[j] < m){
						dp[que.front() + p[j]] = 1;
						que.push(que.front() + p[j]);
					}
				}
				que.pop();
			}
		}
		for (int i = m - 1; i >= 0; i--){
			if (dp[i] != 0){
				cout << i << endl;
				break;
			}
		}
	}
	return 0;
}

C++: //  0529.cpp
//  2012/12/14.

#if 1

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <cassert>
#include <iostream>
#include <cctype>
#include <sstream>
#include <string>
#include <list>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <map>
#include <utility>
#include <numeric>
#include <algorithm>
#include <iterator>
#include <bitset>
#include <complex>
#include <fstream>
using namespace std;
typedef long long ll;
const double EPS = 1e-9;
typedef vector<int> vint;
typedef pair<int, int> pint;
#define rep(i, n) REP(i, 0, n)
#define ALL(v) v.begin(), v.end()
#define MSG(a) cout << #a << " " << a << endl;
#define REP(i, x, n) for(int i = x; i < n; i++)
template<class T> T RoundOff(T a){ return int(a+.5-(a<0)); }
template<class T, class C> void chmax(T& a, C b){ if(a < b) a = b; }
template<class T, class C> void chmin(T& a, C b){ if(b < a) a = b; }
template<class T, class C> pair<T, C> mp(T a, C b){ return make_pair(a, b); }

int main()
{
    for(int N, M; cin >> N >> M && (N || M); )
	{
		vint points(N);
		
		rep(i, N) cin >> points[i];
		points.push_back(0);
		
		vint pair;
		rep(i, N+1) REP(j, i, N+1) pair.push_back(points[i] + points[j]);
		
		sort(ALL(pair));

		int ans = 0;
		rep(i, pair.size())
		{
			int s = M - pair[i];
			
			int idx = lower_bound(ALL(pair), s) - pair.begin() - 1;
			
			if(0 <= idx && pair[i] + pair[idx] <= M) chmax(ans, pair[i] + pair[idx]);
		}
		
		cout << ans << endl;
	}
}

#endif

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

int n, m, point[1001], sum, ans;

int solve(int start, int end, int border){
	int mid;
	while(1){
		if((end + start) % 2){
			mid = (end + start) / 2 + 1;
		} else{
			mid = (end + start) / 2;
		}
		
		if(point[mid] > border){
			end = mid;
		} else{
			start = mid;
		}
		
		if(end - start == 1){
			if(point[end] < border){
				return point[end];
			} else{
				return point[start];
			}
		}
	}
	return mid;
}
int main() {
	while(cin >> n >> m && n && m){
		for(int i = 0; i < n; i++){
			cin >> point[i];
		}
		
		sort(point, point + n + 1);
		
		for(int i = 0; i < n + 1; i++){
			for(int j = 0; j < n + 1; j++){
				for(int k = 0; k < n + 1; k++){
					sum = point[i] + point[j] + point[k];
					if(sum > m){
						continue;
					}
					ans = max(ans, sum + solve(0, n - 1, m - sum));
				}
			}
		}
		
		cout << ans << endl;
		
		memset(point, 0, sizeof(point));
		ans = 0;
	}
	return 0;
}

C++: #include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
using namespace std;
#define INF (1<<30)
typedef pair<int,int> Pa;
int N,M;
int P[1111];
struct Segment{
  Pa T[(1<<21)+1];
  int p[1001*1001+1];
  int n;

  //節点の番号、追加する要素の区間[fi、se)
  void update(int k,int fi,int se){
    k=k+(n/2)-1;
    T[k].first=min(fi,T[k].first);
    T[k].second=max(se,T[k].second);
    while(k>0){//登りながら更新
      k=(k-1)/2;
      T[k].first=min(fi,T[k].first);
      T[k].second=max(se,T[k].second);
    }
  }

  void init(){//ツリー構築

    //P[i]+P[j]の足し算の結果を格納
    for(int i=0;i<N;i++){
      for(int j=0;j<N;j++){
	p[i+j*N]=P[i]+P[j];
	//	printf("%d + %d = %d\n",P[i],P[j],p[i+j*i]);
      }
    }
    //最後にINFを付加
    p[N*N]=INF;
    //昇順ソート
    sort(p,p+N*N+1);
    unique(p,p+N*N+1);
    int _n;
    for(int i=0;i<N*N+1;i++){
      if(p[i]==INF){ _n=i+1; break;}
    }

    //nを2^mに
    n=1;
    while( n < _n*2 ) n*=2;
    
    //木を全て(INF~0)に初期化
    for(int i=0;i<n;i++){
      T[i]=Pa(INF,0);
    }

    //葉を追加
    for(int i=0;i<_n-1;i++){
      //     printf("%d , [%d,%d)\n",i,p[i],p[i+1]);
      update(i,p[i],p[i+1]);
    }  
  }

  //値aより小さくもっと大きい数字は何か探す
  int search(int a){
    return query(0,a);
  }

  //区間[T[k].first,T[k].second)にaあるか否か
  int query(int k,int a){
    if(T[k].first<=a && a<T[k].second){
      if(k>=n/2-1){
	return T[k].first;
      }
      int v=query(k*2+1,a);//左の葉
      if(v!=-1) return v;
      v=query(k*2+2,a);//右の葉
      return v;
    }
    return -1;
  }
  int size(){ return n;}
  void view(){
    printf("size=%d\n",this->size());
    int r=1;
    for(int i=0;i<n;i++){
      if(i==r){puts(""); r=(r+1)*2-1;}
      printf(" [%2d,%2d) ",T[i].first,T[i].second);
    }
  }

};

Segment S;

main(){
  while(1){
    scanf("%d %d",&N,&M);
    if(!N && !M) break;
    for(int i=0;i<N;i++){
      scanf("%d",&P[i]);
    }
    P[N]=0;
    ++N;
    S.init();
    //    S.view();
    int res=0;
    for(int i=0;i<N;i++){
      for(int j=0;j<N;j++){
	int m=M-P[i]-P[j];
	if(m<0) continue;
	int r=S.search(m);
	m-=r;
	//	printf("%d %d ::Seg=%d res=%d\n",P[i],P[j],r,M-m);
	res = max(res,M-m);
      }
    }
    printf("%d\n",res);
  }
}

C++: #include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
    long long n, m;
    while(cin >> n >> m, n){
        vector<long> in(n+1,0),sum;
        for(int i = 0; i < n; i++) cin >> in[i];
        n++;
        for(int i = 0; i < n; i++) for(int j = i; j < n; j++){
            sum.push_back(in[i]+in[j]);
        }
        sort(sum.begin(),sum.end());
        long long ans = 0;
        for(int i = 0; i < sum.size(); i++){
            int t = upper_bound(sum.begin(),sum.end(),m-sum[i])-sum.begin();
            t--;
            long long score = sum[i] + sum[t];
            if(score > m)continue;
            ans = max(ans, score);
        }
        cout << ans << endl;
    }
}