大意:找出不多于四个数的和是<=m的。
思路:二分,我们可以按一个数被用到的次数将他们放到数组里。
1.n个数中<=m的数
2.n个数中任意两个数的和<=m的
然后暴力0-cnt在其中再找到对应两外0-2个数(对应数组的和)。
#include<map>
#include<cmath>
#include<queue>
#include<cmath>
#include<string>
#include<cstdio>
#include<stack>
#include<iostream>
#include<cstring>
#include<algorithm>
#define inf 0x3f3f3f3f
#define eps 1e-8
#define ls l,mid,rt<<1
#define rs mid+1,rt,rt<<1|1
#define LL __int64
#define ll long long
using namespace std;
ll arr[10000010],cnt,m;
ll tmp ;
void so(){
for(int i = 0;i < cnt ;++i){
int l = 0,r = cnt;
while(r > l){
int mid =(r+l)>>1;
ll x = arr[mid];
if(x + arr[i] <= m){
if(x+arr[i] >tmp)
tmp = x+arr[i];
l = mid +1;
}
else
r = mid ;
}
}
}
int main(){
ll n,i,j,k,cla = 1;
while(~scanf("%lld%lld",&n,&m)){
tmp = cnt = 0;
if(!n&&!m) break;
for(i = 0;i < n ;++i){
scanf("%lld",&k);
if(k > m) continue;
arr[cnt++] = k;
}
k = cnt;
for(i = 0;i < cnt ;++ i){
for(j = 0;j < cnt;++ j){
int t= arr[i] + arr[j];
if(t <= m)
arr[k++] = t;
}
}
cnt = k;
sort(arr,arr + cnt);
printf("Case %lld: ",cla++);
if(arr[cnt-1] < 0){
puts("0");
continue;
}
so();
printf("%lld\n\n",tmp);
}
return 0;
}