n, m = map(int, input().split()) cards = [tuple(map(int, input().split())) for _ in range(n)] cards.sort(reverse=True) # c, dの両面で大きい順 # dp[k] は、カードを k 枚選んだときの (cost, score) 状態のリスト(コスト昇順) dp = [[] for _ in range(n+1)] dp[0].append((0, 0)) # 初期状態 for c, d in cards: # k の降順に更新:同じカードからの複数更新を防ぐため for k in range(n-1, -1, -1): new_states = [] for cost, score in dp[k]: new_cost = cost + c * (1 << k) # 2^k を掛ける if new_cost <= m: new_states.append((new_cost, score + d)) if new_states: # dp[k+1] に既存の状態と新状態を併合 combined = dp[k+1] + new_states combined.sort(key=lambda x: x[0]) # コストでソート # ドミネーション除去:コストは低いほどよく、scoreが上回る状態だけを残す filtered = [] best = -1 for cost_val, score_val in combined: if score_val > best: filtered.append((cost_val, score_val)) best = score_val dp[k+1] = filtered ans = 0 for states in dp: if states: ans = max(ans, max(score for cost, score in states)) print(ans)