import sys

N,W = list(map(int, input().split()))

src = []

wmax = vmax = 0

for i in range(N):

  w,v = list(map(int, input().split()))

  src.append((w,v))

  wmax += w

  vmax += v

w1 = src[0][0]



if w1 > W:

  print((0))

  sys.exit()

if wmax <= W:

  print(vmax)

  sys.exit()



wend = 3*N+1

dp = [[0 for w in range(wend)] for n in range(N+1)]

for i in range(N):

  wi,vi = src[i]

  wi -= w1 # 0 <= wi <= 3

  maxn = min(N,i+1)

  for n in reversed(list(range(1,maxn+1))):

    for w in range(wi,wend):

      dp[n][w] = max(dp[n][w], dp[n-1][w-wi] + vi)



ans = 0

for n in range(1,N+1):

  remain = W - w1*n

  if remain < 0: break

  w = min(remain, wend-1)

  ans = max(ans, dp[n][w])



print(ans)
from collections import defaultdict

from copy import copy

N,W = list(map(int,input().split()))

src = [tuple(map(int,input().split())) for i in range(N)]



dp = defaultdict(lambda: 0)

dp[0] = 0

for w,v in src:

    dp2 = copy(dp)

    for pw,pv in list(dp.items()):

        if pw+w > W: continue

        defv = dp[pw+w] if pw+w in dp else 0

        dp2[pw+w] = max(defv, pv+v)

    dp = dp2

print((max(dp.values())))
import sys

N, W = list(map(int, input().split()))
src = []
wmax = vmax = 0
for i in range(N):
    w, v = list(map(int, input().split()))
    src.append((w, v))
    wmax += w
    vmax += v
w1 = src[0][0]
if w1 > W:
    print((0))
    sys.exit()
if wmax <= W:
    print(vmax)
    sys.exit()
wend = 3 * N + 1
dp = [[0 for w in range(wend)] for n in range(N + 1)]
for i in range(N):
    wi, vi = src[i]
    wi -= w1  # 0 <= wi <= 3
    maxn = min(N, i + 1)
    for n in reversed(list(range(1, maxn + 1))):
        for w in range(wi, wend):
            dp[n][w] = max(dp[n][w], dp[n - 1][w - wi] + vi)
ans = 0
for n in range(1, N + 1):
    remain = W - w1 * n
    if remain < 0:
        break
    w = min(remain, wend - 1)
    ans = max(ans, dp[n][w])
print(ans)

from collections import defaultdict
from copy import copy

N, W = list(map(int, input().split()))
src = [tuple(map(int, input().split())) for i in range(N)]
dp = defaultdict(lambda: 0)
dp[0] = 0
for w, v in src:
    dp2 = copy(dp)
    for pw, pv in list(dp.items()):
        if pw + w > W:
            continue
        defv = dp[pw + w] if pw + w in dp else 0
        dp2[pw + w] = max(defv, pv + v)
    dp = dp2
print((max(dp.values())))

-import sys +from collections import defaultdict +from copy import copy -src = [] -wmax = vmax = 0 -for i in range(N): -    w, v = list(map(int, input().split())) -    src.append((w, v)) -    wmax += w -    vmax += v -w1 = src[0][0] -if w1 > W: -    print((0)) -    sys.exit() -if wmax <= W: -    print(vmax) -    sys.exit() -wend = 3 * N + 1 -dp = [[0 for w in range(wend)] for n in range(N + 1)] -for i in range(N): -    wi, vi = src[i] -    wi -= w1  # 0 <= wi <= 3 -    maxn = min(N, i + 1) -    for n in reversed(list(range(1, maxn + 1))): -        for w in range(wi, wend): -            dp[n][w] = max(dp[n][w], dp[n - 1][w - wi] + vi) -ans = 0 -for n in range(1, N + 1): -    remain = W - w1 * n -    if remain < 0: -        break -    w = min(remain, wend - 1) -    ans = max(ans, dp[n][w]) -print(ans) +src = [tuple(map(int, input().split())) for i in range(N)] +dp = defaultdict(lambda: 0) +dp[0] = 0 +for w, v in src: +    dp2 = copy(dp) +    for pw, pv in list(dp.items()): +        if pw + w > W: +            continue +        defv = dp[pw + w] if pw + w in dp else 0 +        dp2[pw + w] = max(defv, pv + v) +    dp = dp2 +print((max(dp.values())))