from bisect import bisect from collections import defaultdict from itertools import accumulate def solve(n, W, vw): vw.sort(key=lambda x: x[0] / x[1], reverse=True) vs = [] ws = [] wei_to_val = defaultdict(int) wei_to_val[0] = 0 for v, w in vw: vs.append(v) ws.append(w) cum_v, cum_w = [0] + list(accumulate(vs)), [0] + list(accumulate(ws)) cum_v.append(cum_v[-1]) res = cum_v[bisect(cum_w, W) - 1] for i, (v, w) in enumerate(vw): cur_w = W + cum_w[i] del_v = cum_v[i] for w2, v2 in list(wei_to_val.items()): if w2 + w > W: continue j = bisect(cum_w, cur_w - w2) - 1 tmp_ans = v2 + cum_v[j] - del_v if j < n - 1: plus = vs[j] * (cur_w - w2 - cum_w[j]) / ws[j] else: plus = 0 if tmp_ans + plus <= res: del wei_to_val[w2] continue res = max(res, tmp_ans) wei_to_val[w2 + w] = max(wei_to_val[w2 + w], v2 + v) return res n, W = map(int, input().split()) vw = [list(map(int, input().split())) for i in range(n)] print(solve(n, W, vw))