## https://yukicoder.me/problems/no/3401 def calc_gcd(A, B): """ 正の整数A, Bの最大公約数を計算する """ a = max(A, B) b = min(A, B) while a % b > 0: c = a % b a = b b = c return b from functools import cmp_to_key # 比較関数 def compare_items(a, b): if a[0] * b[1] > b[0] * a[1]: return 1 elif a[0] * b[1] < b[0] * a[1]: return -1 else: return 0 def main(): N, W = map(int, input().split()) vw = [] for _ in range(N): v, w = map(int, input().split()) vw.append((v, w)) # wについて一意にする w_map = {} for v, w in vw: if w not in w_map: w_map[w] = -1 w_map[w] = max(v, w_map[w]) new_wv = list([(key, value) for key, value in w_map.items()]) # カスタム比較関数を使ってリストをソート new_wv = sorted(new_wv, key=cmp_to_key(compare_items)) max_w, max_v = new_wv[0] w0 = max([w for w, _ in new_wv]) * max([w for w, _ in new_wv]) border_w = min(w0, W) dp = [-1] * (border_w + 1) dp[0] = 0 for w, v in new_wv: new_dp = [-1] * (border_w + 1) xx = [-1] * w for x in range(border_w + 1): y0 = x // w y1 = x % w if dp[x] >= 0: new_dp[x] = max(new_dp[x], dp[x]) xx[y1] = max(xx[y1], dp[x] - y0 * v) if xx[y1] >= 0: new_dp[x] = max(new_dp[x], xx[y1] + y0 * v) dp = new_dp answer = -1 for w in reversed(range(border_w + 1)): if dp[w] >= 0: w1 = W - w count = w1 // max_w ans = dp[w] + count * max_v answer = max(answer, ans) print(answer) if __name__ == "__main__": main()