from collections import *

from heapq import *

from itertools import *

from fractions import gcd

import sys

from decimal import *

import copy

from bisect import *

input=lambda :sys.stdin.readline().rstrip()

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

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



lst=[]

for w,v in WV:

    for i in range(len(lst)):

        w1,v1=lst[i]

        if w1:

            lst.append([w1+w,v1+v])

    lst.append([w,v])



    lst=sorted(lst,key=lambda x:x[0],reverse=True)

    while lst and lst[-1][0]==0:

        lst.pop()



    w,v=lst[-1]

    for i in range(len(lst)-1)[::-1]:

        w1,v1=lst[i]

        if v1<=v:

            lst[i][0]=0

            lst[i][1]=0

        else:

            v=v1

    #print(lst)

print((max([v for w,v in lst if w<=W])))

from collections import *

from heapq import *

from itertools import *

from fractions import gcd

import sys

from decimal import *

import copy

from bisect import *

input=lambda :sys.stdin.readline().rstrip()

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

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



lst=deque([])

for w,v in WV:

    nlst=deque([[w,v]])

    for i in range(len(lst)):

        w1,v1=lst[i]

        if w1+w<=W:

            if w1:

                nlst.append([w1+w,v1+v])

    if not lst:

        lst=copy.copy(nlst)

        continue

    Xlst=lst

    lst=deque()



    if Xlst or nlst:

        w1,v1=nlst[0]

        w2,v2=Xlst[0]

        if w1<w2:

            lst.append(nlst.popleft())

        else:

            lst.append(Xlst.popleft())

    while Xlst or nlst:

        w,v=lst[-1]

        if Xlst and nlst:

            w1,v1=nlst[0]

            w2,v2=Xlst[0]



            if w==w1:

                if v>=v1:

                    nlst.popleft()

                else:

                    lst.pop()

                    lst.append(nlst.popleft())

            elif w==w2:

                if v>=v2:

                    Xlst.popleft()

                else:

                    lst.pop()

                    lst.append(Xlst.popleft())

            else:

                if w1<w2:

                    if v>=v1:

                        nlst.popleft()

                    else:

                        lst.append(nlst.popleft())

                else:

                    if v>=v2:

                        Xlst.popleft()

                    else:

                        lst.append(Xlst.popleft())

        elif nlst:

            w1,v1=nlst[0]

            if w==w1:

                if v>=v1:

                    nlst.popleft()

                else:

                    lst.pop()

                    lst.append(nlst.popleft())

            else:

                if v>=v1:

                    nlst.popleft()

                else:

                    lst.append(nlst.popleft())

        elif Xlst:

            nlst=Xlst

            Xlst=deque()







lst.append([0,0])

print((max([v for w,v in lst if w<=W])))

from collections import *
from heapq import *
from itertools import *
from fractions import gcd
import sys
from decimal import *
import copy
from bisect import *

input = lambda: sys.stdin.readline().rstrip()
N, W = list(map(int, input().split()))
WV = [list(map(int, input().split())) for i in range(N)]
lst = []
for w, v in WV:
    for i in range(len(lst)):
        w1, v1 = lst[i]
        if w1:
            lst.append([w1 + w, v1 + v])
    lst.append([w, v])
    lst = sorted(lst, key=lambda x: x[0], reverse=True)
    while lst and lst[-1][0] == 0:
        lst.pop()
    w, v = lst[-1]
    for i in range(len(lst) - 1)[::-1]:
        w1, v1 = lst[i]
        if v1 <= v:
            lst[i][0] = 0
            lst[i][1] = 0
        else:
            v = v1
    # print(lst)
print((max([v for w, v in lst if w <= W])))

from collections import *
from heapq import *
from itertools import *
from fractions import gcd
import sys
from decimal import *
import copy
from bisect import *

input = lambda: sys.stdin.readline().rstrip()
N, W = list(map(int, input().split()))
WV = [list(map(int, input().split())) for i in range(N)]
lst = deque([])
for w, v in WV:
    nlst = deque([[w, v]])
    for i in range(len(lst)):
        w1, v1 = lst[i]
        if w1 + w <= W:
            if w1:
                nlst.append([w1 + w, v1 + v])
    if not lst:
        lst = copy.copy(nlst)
        continue
    Xlst = lst
    lst = deque()
    if Xlst or nlst:
        w1, v1 = nlst[0]
        w2, v2 = Xlst[0]
        if w1 < w2:
            lst.append(nlst.popleft())
        else:
            lst.append(Xlst.popleft())
    while Xlst or nlst:
        w, v = lst[-1]
        if Xlst and nlst:
            w1, v1 = nlst[0]
            w2, v2 = Xlst[0]
            if w == w1:
                if v >= v1:
                    nlst.popleft()
                else:
                    lst.pop()
                    lst.append(nlst.popleft())
            elif w == w2:
                if v >= v2:
                    Xlst.popleft()
                else:
                    lst.pop()
                    lst.append(Xlst.popleft())
            else:
                if w1 < w2:
                    if v >= v1:
                        nlst.popleft()
                    else:
                        lst.append(nlst.popleft())
                else:
                    if v >= v2:
                        Xlst.popleft()
                    else:
                        lst.append(Xlst.popleft())
        elif nlst:
            w1, v1 = nlst[0]
            if w == w1:
                if v >= v1:
                    nlst.popleft()
                else:
                    lst.pop()
                    lst.append(nlst.popleft())
            else:
                if v >= v1:
                    nlst.popleft()
                else:
                    lst.append(nlst.popleft())
        elif Xlst:
            nlst = Xlst
            Xlst = deque()
lst.append([0, 0])
print((max([v for w, v in lst if w <= W])))

-lst = [] +lst = deque([]) +    nlst = deque([[w, v]]) -        if w1: -            lst.append([w1 + w, v1 + v]) -    lst.append([w, v]) -    lst = sorted(lst, key=lambda x: x[0], reverse=True) -    while lst and lst[-1][0] == 0: -        lst.pop() -    w, v = lst[-1] -    for i in range(len(lst) - 1)[::-1]: -        w1, v1 = lst[i] -        if v1 <= v: -            lst[i][0] = 0 -            lst[i][1] = 0 +        if w1 + w <= W: +            if w1: +                nlst.append([w1 + w, v1 + v]) +    if not lst: +        lst = copy.copy(nlst) +        continue +    Xlst = lst +    lst = deque() +    if Xlst or nlst: +        w1, v1 = nlst[0] +        w2, v2 = Xlst[0] +        if w1 < w2: +            lst.append(nlst.popleft()) -            v = v1 -    # print(lst) +            lst.append(Xlst.popleft()) +    while Xlst or nlst: +        w, v = lst[-1] +        if Xlst and nlst: +            w1, v1 = nlst[0] +            w2, v2 = Xlst[0] +            if w == w1: +                if v >= v1: +                    nlst.popleft() +                else: +                    lst.pop() +                    lst.append(nlst.popleft()) +            elif w == w2: +                if v >= v2: +                    Xlst.popleft() +                else: +                    lst.pop() +                    lst.append(Xlst.popleft()) +            else: +                if w1 < w2: +                    if v >= v1: +                        nlst.popleft() +                    else: +                        lst.append(nlst.popleft()) +                else: +                    if v >= v2: +                        Xlst.popleft() +                    else: +                        lst.append(Xlst.popleft()) +        elif nlst: +            w1, v1 = nlst[0] +            if w == w1: +                if v >= v1: +                    nlst.popleft() +                else: +                    lst.pop() +                    lst.append(nlst.popleft()) +            else: +                if v >= v1: +                    nlst.popleft() +                else: +                    lst.append(nlst.popleft()) +        elif Xlst: +            nlst = Xlst +            Xlst = deque() +lst.append([0, 0])