# coding: utf-8

# Your code here!

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

dp=[[-1]*301 for i in range(N+1)]

dp[0][0]=0



for i in range(N):

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

    if i==0:

        base=w

    for i in range(N)[::-1]:

        for j in range(301)[::-1]:

            if dp[i][j]!=-1:

                dp[i+1][j+w-base]=max(dp[i][j]+v,dp[i+1][j+w-base])



ans=0

for index,item in enumerate(dp):

    if W-index*base+1<=0:

        break

    ans=max(max(item[:W-index*base+1]),ans)

    #print(item[:W-index*base+1])



print(ans)

# coding: utf-8

# Your code here!

def saiki(value,HP,num):

    if num==0:

        #print(HP//base)

        value+=wa[0][min(HP//base,len(wa[0])-1)]

        ans.append(value)

    else:

        for i in range(len(wa[num])):

            if HP-(num+base)*i>=0:

                saiki(value+wa[num][i],HP-(num+base)*i,num-1)

            else:

                break

    return





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



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



for i in range(N):

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

    if i==0:

        base=w

    lis[w-base].append(v)



lis=list([sorted(x, reverse=True) for x in lis])



wa=[[0] for i in range(4)]



for i in range(len(wa)):

    for item in lis[i]:

        wa[i].append(wa[i][-1]+item)



#print(wa)



ans=[]

saiki(0,W,3)

    



print((max(ans)))

    
# coding: utf-8
# Your code here!
N, W = list(map(int, input().split()))
dp = [[-1] * 301 for i in range(N + 1)]
dp[0][0] = 0
for i in range(N):
    w, v = list(map(int, input().split()))
    if i == 0:
        base = w
    for i in range(N)[::-1]:
        for j in range(301)[::-1]:
            if dp[i][j] != -1:
                dp[i + 1][j + w - base] = max(dp[i][j] + v, dp[i + 1][j + w - base])
ans = 0
for index, item in enumerate(dp):
    if W - index * base + 1 <= 0:
        break
    ans = max(max(item[: W - index * base + 1]), ans)
    # print(item[:W-index*base+1])
print(ans)

# coding: utf-8
# Your code here!
def saiki(value, HP, num):
    if num == 0:
        # print(HP//base)
        value += wa[0][min(HP // base, len(wa[0]) - 1)]
        ans.append(value)
    else:
        for i in range(len(wa[num])):
            if HP - (num + base) * i >= 0:
                saiki(value + wa[num][i], HP - (num + base) * i, num - 1)
            else:
                break
    return


N, W = list(map(int, input().split()))
lis = [[] for i in range(4)]
for i in range(N):
    w, v = list(map(int, input().split()))
    if i == 0:
        base = w
    lis[w - base].append(v)
lis = list([sorted(x, reverse=True) for x in lis])
wa = [[0] for i in range(4)]
for i in range(len(wa)):
    for item in lis[i]:
        wa[i].append(wa[i][-1] + item)
# print(wa)
ans = []
saiki(0, W, 3)
print((max(ans)))

+def saiki(value, HP, num): +    if num == 0: +        # print(HP//base) +        value += wa[0][min(HP // base, len(wa[0]) - 1)] +        ans.append(value) +    else: +        for i in range(len(wa[num])): +            if HP - (num + base) * i >= 0: +                saiki(value + wa[num][i], HP - (num + base) * i, num - 1) +            else: +                break +    return + + -dp = [[-1] * 301 for i in range(N + 1)] -dp[0][0] = 0 +lis = [[] for i in range(4)] -    for i in range(N)[::-1]: -        for j in range(301)[::-1]: -            if dp[i][j] != -1: -                dp[i + 1][j + w - base] = max(dp[i][j] + v, dp[i + 1][j + w - base]) -ans = 0 -for index, item in enumerate(dp): -    if W - index * base + 1 <= 0: -        break -    ans = max(max(item[: W - index * base + 1]), ans) -    # print(item[:W-index*base+1]) -print(ans) +    lis[w - base].append(v) +lis = list([sorted(x, reverse=True) for x in lis]) +wa = [[0] for i in range(4)] +for i in range(len(wa)): +    for item in lis[i]: +        wa[i].append(wa[i][-1] + item) +# print(wa) +ans = [] +saiki(0, W, 3) +print((max(ans)))