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

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

goods=[[v],[],[],[]]

for i in range(N-1):

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

    goods[w-w0].append(v)

val=[]

for x in range(4):

    goods[x].sort(reverse=True)

    valx=[0]*(len(goods[x])+1)

    for k in range(len(goods[x])):

        valx[k+1]=valx[k]+goods[x][k]

    val.append(valx)

ans=0

for i in range(len(goods[0])+1):

    if w0*i>W:

        break

    for j in range(len(goods[1])+1):

        if w0*(i+j)+j>W:

            break

        for k in range(len(goods[2])+1):

            if w0*(i+j+k)+j+2*k>W:

                break

            for l in range(len(goods[3])+1):

                if w0*(i+j+k+l)+j+2*k+3*l>W:

                    break

                ans=max(ans,val[0][i]+val[1][j]+val[2][k]+val[3][l])

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

goods=[[] for i in range(4)]

w1=-1

for i in range(N):

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

    if i==0:

        w1=w

    goods[w-w1].append(v)

S=[]

for x in range(4):

    goods[x].sort(reverse=True)

    G=goods[x]

    now=[0]*(len(G)+1)

    for i in range(len(G)):

        now[i+1]=now[i]+G[i]

    S.append(now)

ans=0

for i in range(1+len(goods[0])):

    for j in range(1+len(goods[1])):

        for k in range(1+len(goods[2])):

            wnow=W-w1*(i+j+k)-j-2*k

            if wnow<0:

                continue

            else:

                ans=max(ans,S[0][i]+S[1][j]+S[2][k]+S[3][min(len(S[3])-1,wnow//(w1+3))])

print(ans)
N, W = list(map(int, input().split()))
w0, v = list(map(int, input().split()))
goods = [[v], [], [], []]
for i in range(N - 1):
    w, v = list(map(int, input().split()))
    goods[w - w0].append(v)
val = []
for x in range(4):
    goods[x].sort(reverse=True)
    valx = [0] * (len(goods[x]) + 1)
    for k in range(len(goods[x])):
        valx[k + 1] = valx[k] + goods[x][k]
    val.append(valx)
ans = 0
for i in range(len(goods[0]) + 1):
    if w0 * i > W:
        break
    for j in range(len(goods[1]) + 1):
        if w0 * (i + j) + j > W:
            break
        for k in range(len(goods[2]) + 1):
            if w0 * (i + j + k) + j + 2 * k > W:
                break
            for l in range(len(goods[3]) + 1):
                if w0 * (i + j + k + l) + j + 2 * k + 3 * l > W:
                    break
                ans = max(ans, val[0][i] + val[1][j] + val[2][k] + val[3][l])
print(ans)

N, W = list(map(int, input().split()))
goods = [[] for i in range(4)]
w1 = -1
for i in range(N):
    w, v = list(map(int, input().split()))
    if i == 0:
        w1 = w
    goods[w - w1].append(v)
S = []
for x in range(4):
    goods[x].sort(reverse=True)
    G = goods[x]
    now = [0] * (len(G) + 1)
    for i in range(len(G)):
        now[i + 1] = now[i] + G[i]
    S.append(now)
ans = 0
for i in range(1 + len(goods[0])):
    for j in range(1 + len(goods[1])):
        for k in range(1 + len(goods[2])):
            wnow = W - w1 * (i + j + k) - j - 2 * k
            if wnow < 0:
                continue
            else:
                ans = max(
                    ans,
                    S[0][i]
                    + S[1][j]
                    + S[2][k]
                    + S[3][min(len(S[3]) - 1, wnow // (w1 + 3))],
                )
print(ans)

-w0, v = list(map(int, input().split())) -goods = [[v], [], [], []] -for i in range(N - 1): +goods = [[] for i in range(4)] +w1 = -1 +for i in range(N): -    goods[w - w0].append(v) -val = [] +    if i == 0: +        w1 = w +    goods[w - w1].append(v) +S = [] -    valx = [0] * (len(goods[x]) + 1) -    for k in range(len(goods[x])): -        valx[k + 1] = valx[k] + goods[x][k] -    val.append(valx) +    G = goods[x] +    now = [0] * (len(G) + 1) +    for i in range(len(G)): +        now[i + 1] = now[i] + G[i] +    S.append(now) -for i in range(len(goods[0]) + 1): -    if w0 * i > W: -        break -    for j in range(len(goods[1]) + 1): -        if w0 * (i + j) + j > W: -            break -        for k in range(len(goods[2]) + 1): -            if w0 * (i + j + k) + j + 2 * k > W: -                break -            for l in range(len(goods[3]) + 1): -                if w0 * (i + j + k + l) + j + 2 * k + 3 * l > W: -                    break -                ans = max(ans, val[0][i] + val[1][j] + val[2][k] + val[3][l]) +for i in range(1 + len(goods[0])): +    for j in range(1 + len(goods[1])): +        for k in range(1 + len(goods[2])): +            wnow = W - w1 * (i + j + k) - j - 2 * k +            if wnow < 0: +                continue +            else: +                ans = max( +                    ans, +                    S[0][i] +                    + S[1][j] +                    + S[2][k] +                    + S[3][min(len(S[3]) - 1, wnow // (w1 + 3))], +                )