import sys
from collections import deque
import copy

from math import *

def get_read_func(fileobject):
    if fileobject == None :
        return raw_input
    else:
        return fileobject.readline


def main():
    if len(sys.argv) > 1:
        f = open(sys.argv[1])
    else:
        f = None
    read_func = get_read_func(f);
    input_raw = read_func().strip().split()
    [N, W] =  [long(input_raw[0]), long(input_raw[1])]
    v = []
    w = []
    for i in range(N):
        input_raw = read_func().strip().split()
        [wi, vi] =  [long(input_raw[0]), long(input_raw[1])]
        v.append(vi)
        w.append(wi)

    W_ = long(N * 100)
    dp = [[0L for j in range((W_) + 1)] for i in range(N + 1)]

    for i in range(N):
        for j in range(W_ + 1):
            k = max(0, ((j + w[0] - 1) - w[i]) - w[0] + 1)
            #print k, j, w[i]
            if (j + w[0] - 1) - w[i]  < 0:
                dp[i + 1][j] = dp[i][j]
            else:
                dp[i + 1][j] = max(dp[i][j], dp[i][k] + v[i])


    print dp[N][max(0, W - w[0] + 1)]


if __name__ == '__main__':
    main()

### FIXED CODE ###

import sys
from collections import deque
import copy

from math import *

def get_read_func(fileobject):
    if fileobject == None :
        return raw_input
    else:
        return fileobject.readline


def main():
    if len(sys.argv) > 1:
        f = open(sys.argv[1])
    else:
        f = None
    read_func = get_read_func(f);
    input_raw = read_func().strip().split()
    [N, W] =  [long(input_raw[0]), long(input_raw[1])]
    v = []
    item = {}
    v_sum = {}
    for i in range(N):
        input_raw = read_func().strip().split()
        [wi, vi] =  [long(input_raw[0]), long(input_raw[1])]
        if wi not in item:
            item[wi] = [vi]
        else:
            item[wi].append(vi)

    for i in range(4 - len(item)):
        item[long(-(i + 1))] = [0L]

    w_list = []
    for wi in item:
        item[wi].sort(reverse = True)
        w_list.append(wi)
        v_sum[wi] = [0L for i in range(len(item[wi]) + 1)]
        v_sum[wi][1] = item[wi][0]
        for i in range(1, len(item[wi])):
            v_sum[wi][i + 1] = v_sum[wi][i] + item[wi][i]

    max_value = 0L
    for i in range(len(item[w_list[0]]) + 1):
        for j in range(len(item[w_list[1]]) + 1):
            for k in range(len(item[w_list[2]]) + 1):
                for l in range(len(item[w_list[3]]) + 1):
                    if W - (i * max(0L, w_list[0]) + j * max(0L, w_list[1]) + k * max(0L, w_list[2]) + l * max(0L, w_list[3])) >= 0:
                        value = v_sum[w_list[0]][i] + v_sum[w_list[1]][j] + v_sum[w_list[2]][k] + v_sum[w_list[3]][l]
                        if max_value < value:
                            max_value = value
    print max_value

##    W_ = long(N * 4 + 1)
##    dp = [[0L for j in range((W_) + 1)] for i in range(N + 1)]
##
##    for i in range(N):
##        for j in range(W_ + 1):
##
##            k = ((j - 1)%4 +  ((j - 1)/4 +1) * w[0]) - w[i]
##            #print k, j, w[i]
##            if k  < 0 or j == 0:
##                dp[i + 1][j] = dp[i][j]
##            else:
##                if k >= w[0]:
##                    l = k / w[0] + 3 * (k / w[0] - 1)
##                else:
##                    l = 0
##                print i ,w[i], k, l
##                dp[i + 1][j] = max(dp[i][j], dp[i][l] + v[i])
##
##    maximum = 0
##    for i in range(1, W_ + 1):
##        if maximum < dp[N][i] and (i - 1)%4 +  ((i - 1)/4 +1) * w[0] <= W:
##            maximum = dp[N][i]
##
##    print maximum


if __name__ == '__main__':
    main()