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

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



w0 = items[0][0]

sizeX = min(W, sum([items[i][0] for i in range(N)])) // w0 + 1

sizeY = min(w0, 3 * (N - 1) + 1)

memo = [[[-1 for y in range(sizeY)] for x in range(sizeX)] for i in range(N + 1)]



memo[0][0][0] = 0

for i, (wi, vi) in enumerate(items):

    for x in range(sizeX):

        for y in range(sizeY):

            if memo[i][x][y] == -1: continue



            wn = w0 * x + y + wi

            if wn <= W:

                memo[i + 1][wn // w0][wn % w0] = memo[i][x][y] + vi



            memo[i + 1][x][y] = max(memo[i + 1][x][y], memo[i][x][y])



print((max(list(map(max, [memo[N][x] for x in range(sizeX)])))))

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

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



memo = [{} for i in range(N + 1)]



memo[0] = {0: 0}

for i, (wi, vi) in enumerate(items):

    for w, v in list(memo[i].items()):



        if w + wi <= W:

            memo[i + 1][w + wi] = max(memo[i + 1].get(w + wi, 0), v + vi)



        memo[i + 1][w] = max(memo[i + 1].get(w, 0), v)



print((max(memo[N].values())))

N, W = list(map(int, input().split()))
items = [tuple(map(int, input().split())) for i in range(N)]
w0 = items[0][0]
sizeX = min(W, sum([items[i][0] for i in range(N)])) // w0 + 1
sizeY = min(w0, 3 * (N - 1) + 1)
memo = [[[-1 for y in range(sizeY)] for x in range(sizeX)] for i in range(N + 1)]
memo[0][0][0] = 0
for i, (wi, vi) in enumerate(items):
    for x in range(sizeX):
        for y in range(sizeY):
            if memo[i][x][y] == -1:
                continue
            wn = w0 * x + y + wi
            if wn <= W:
                memo[i + 1][wn // w0][wn % w0] = memo[i][x][y] + vi
            memo[i + 1][x][y] = max(memo[i + 1][x][y], memo[i][x][y])
print((max(list(map(max, [memo[N][x] for x in range(sizeX)])))))

N, W = list(map(int, input().split()))
items = [tuple(map(int, input().split())) for i in range(N)]
memo = [{} for i in range(N + 1)]
memo[0] = {0: 0}
for i, (wi, vi) in enumerate(items):
    for w, v in list(memo[i].items()):
        if w + wi <= W:
            memo[i + 1][w + wi] = max(memo[i + 1].get(w + wi, 0), v + vi)
        memo[i + 1][w] = max(memo[i + 1].get(w, 0), v)
print((max(memo[N].values())))

-w0 = items[0][0] -sizeX = min(W, sum([items[i][0] for i in range(N)])) // w0 + 1 -sizeY = min(w0, 3 * (N - 1) + 1) -memo = [[[-1 for y in range(sizeY)] for x in range(sizeX)] for i in range(N + 1)] -memo[0][0][0] = 0 +memo = [{} for i in range(N + 1)] +memo[0] = {0: 0} -    for x in range(sizeX): -        for y in range(sizeY): -            if memo[i][x][y] == -1: -                continue -            wn = w0 * x + y + wi -            if wn <= W: -                memo[i + 1][wn // w0][wn % w0] = memo[i][x][y] + vi -            memo[i + 1][x][y] = max(memo[i + 1][x][y], memo[i][x][y]) -print((max(list(map(max, [memo[N][x] for x in range(sizeX)]))))) +    for w, v in list(memo[i].items()): +        if w + wi <= W: +            memo[i + 1][w + wi] = max(memo[i + 1].get(w + wi, 0), v + vi) +        memo[i + 1][w] = max(memo[i + 1].get(w, 0), v) +print((max(memo[N].values())))