import sys

from collections import *

import heapq

import math

import bisect

from itertools import permutations,accumulate,combinations,product

from fractions import gcd

def input():

    return sys.stdin.readline()[:-1]

def ruiseki(lst):

    return [0]+list(accumulate(lst))

mod=pow(10,9)+7

al=[chr(ord('a') + i) for i in range(26)]



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

wv=[list(map(int,input().split())) for i in range(n)]



dp=[[-float('inf')]*101*400 for i in range(n+1)]

dp[0][0]=0



kijun=wv[0][0]

for i in range(n):

    for j in range(101*400):

        if dp[i][j]!=-float('inf'):

            dp[i+1][j]=max(dp[i+1][j],dp[i][j])

            ko,a=j//400,j%400

            dp[i+1][(ko+1)*400+a+wv[i][0]-kijun]=max(dp[i+1][(ko+1)*400+a+wv[i][0]-kijun],dp[i][j]+wv[i][1])



ans=0

for i in range(101*400):

    ko,a=i//400,i%400

    if ko*kijun+a<=w:

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

print(ans)
import sys

from collections import *

import heapq

import math

import bisect

from itertools import permutations,accumulate,combinations,product

from fractions import gcd

def input():

    return sys.stdin.readline()[:-1]

def ruiseki(lst):

    return [0]+list(accumulate(lst))

mod=pow(10,9)+7

al=[chr(ord('a') + i) for i in range(26)]



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

wv=[list(map(int,input().split())) for i in range(n)]



w1=wv[0][0]

wv.sort()

lst=[[],[],[],[]]

for i in range(n):

    w,v=wv[i]

    lst[w-w1].append(v)

# print(lst)

ruilst=[]

for i in range(4):

    ruilst.append(ruiseki(lst[i][::-1]))

# print(ruilst)



ans=0

for i in range(len(ruilst[0])):

    for j in range(len(ruilst[1])):

        for k in range(len(ruilst[2])):

            for l in range(len(ruilst[3])):

                if i*w1+j*(w1+1)+k*(w1+2)+l*(w1+3)<=W:

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

print(ans)
import sys
from collections import *
import heapq
import math
import bisect
from itertools import permutations, accumulate, combinations, product
from fractions import gcd


def input():
    return sys.stdin.readline()[:-1]


def ruiseki(lst):
    return [0] + list(accumulate(lst))


mod = pow(10, 9) + 7
al = [chr(ord("a") + i) for i in range(26)]
n, w = list(map(int, input().split()))
wv = [list(map(int, input().split())) for i in range(n)]
dp = [[-float("inf")] * 101 * 400 for i in range(n + 1)]
dp[0][0] = 0
kijun = wv[0][0]
for i in range(n):
    for j in range(101 * 400):
        if dp[i][j] != -float("inf"):
            dp[i + 1][j] = max(dp[i + 1][j], dp[i][j])
            ko, a = j // 400, j % 400
            dp[i + 1][(ko + 1) * 400 + a + wv[i][0] - kijun] = max(
                dp[i + 1][(ko + 1) * 400 + a + wv[i][0] - kijun], dp[i][j] + wv[i][1]
            )
ans = 0
for i in range(101 * 400):
    ko, a = i // 400, i % 400
    if ko * kijun + a <= w:
        ans = max(ans, dp[n][i])
print(ans)

import sys
from collections import *
import heapq
import math
import bisect
from itertools import permutations, accumulate, combinations, product
from fractions import gcd


def input():
    return sys.stdin.readline()[:-1]


def ruiseki(lst):
    return [0] + list(accumulate(lst))


mod = pow(10, 9) + 7
al = [chr(ord("a") + i) for i in range(26)]
n, W = list(map(int, input().split()))
wv = [list(map(int, input().split())) for i in range(n)]
w1 = wv[0][0]
wv.sort()
lst = [[], [], [], []]
for i in range(n):
    w, v = wv[i]
    lst[w - w1].append(v)
# print(lst)
ruilst = []
for i in range(4):
    ruilst.append(ruiseki(lst[i][::-1]))
# print(ruilst)
ans = 0
for i in range(len(ruilst[0])):
    for j in range(len(ruilst[1])):
        for k in range(len(ruilst[2])):
            for l in range(len(ruilst[3])):
                if i * w1 + j * (w1 + 1) + k * (w1 + 2) + l * (w1 + 3) <= W:
                    ans = max(
                        ans, ruilst[0][i] + ruilst[1][j] + ruilst[2][k] + ruilst[3][l]
                    )
print(ans)

-n, w = list(map(int, input().split())) +n, W = list(map(int, input().split())) -dp = [[-float("inf")] * 101 * 400 for i in range(n + 1)] -dp[0][0] = 0 -kijun = wv[0][0] +w1 = wv[0][0] +wv.sort() +lst = [[], [], [], []] -    for j in range(101 * 400): -        if dp[i][j] != -float("inf"): -            dp[i + 1][j] = max(dp[i + 1][j], dp[i][j]) -            ko, a = j // 400, j % 400 -            dp[i + 1][(ko + 1) * 400 + a + wv[i][0] - kijun] = max( -                dp[i + 1][(ko + 1) * 400 + a + wv[i][0] - kijun], dp[i][j] + wv[i][1] -            ) +    w, v = wv[i] +    lst[w - w1].append(v) +# print(lst) +ruilst = [] +for i in range(4): +    ruilst.append(ruiseki(lst[i][::-1])) +# print(ruilst) -for i in range(101 * 400): -    ko, a = i // 400, i % 400 -    if ko * kijun + a <= w: -        ans = max(ans, dp[n][i]) +for i in range(len(ruilst[0])): +    for j in range(len(ruilst[1])): +        for k in range(len(ruilst[2])): +            for l in range(len(ruilst[3])): +                if i * w1 + j * (w1 + 1) + k * (w1 + 2) + l * (w1 + 3) <= W: +                    ans = max( +                        ans, ruilst[0][i] + ruilst[1][j] + ruilst[2][k] + ruilst[3][l] +                    )