output_description: Print the maximum possible total value of the selected items.
  
  * * *
input_description: Input is given from Standard Input in the following format:
  
      
      
      N W
      w_1 v_1
      w_2 v_2
      :
      w_N v_N
attempt: import math
  
  # import sys
  # input = sys.stdin.readline
  
  
  def make_divisors(n):
      divisors = []
      for i in range(1, int(n**0.5) + 1):
          if n % i == 0:
              divisors.append(i)
              if i != n // i:
                  divisors.append(n // i)
  
      # divisors.sort()
      return divisors
  
  
  def ValueToBits(x, digit):
      res = [0 for i in range(digit)]
      now = x
      for i in range(digit):
          res[i] = now % 2
          now = now >> 1
      return res
  
  
  def BitsToValue(arr):
      n = len(arr)
      ans = 0
      for i in range(n):
          ans += arr[i] * 2**i
      return ans
  
  
  def ZipArray(a):
      aa = [[a[i], i] for i in range(n)]
  
      aa.sort(key=lambda x: x[0])
      for i in range(n):
          aa[i][0] = i + 1
      aa.sort(key=lambda x: x[1])
      b = [aa[i][0] for i in range(len(a))]
      return b
  
  
  def ValueToArray10(x, digit):
      ans = [0 for i in range(digit)]
      now = x
      for i in range(digit):
          ans[digit - i - 1] = now % 10
          now = now // 10
      return ans
  
  
  def Zeros(a, b):
      if b <= -1:
          return [0 for i in range(a)]
      else:
          return [[0 for i in range(b)] for i in range(a)]
  
  
  def AddV2(v, w):
      return [v[0] + w[0], v[1] + w[1]]
  
  
  dir4 = [[1, 0], [0, 1], [-1, 0], [0, -1]]
  
  
  def clamp(x, y, z):
      return max(y, min(z, x))
  
  
  class Bit:
      def __init__(self, n):
          self.size = n
          self.tree = [0] * (n + 1)
  
      def sum(self, i):
          s = 0
          while i > 0:
              s += self.tree[i]
              i -= i & -i
          return s
  
      def add(self, i, x):
          while i <= self.size:
              self.tree[i] += x
              i += i & -i
  
  
  #
  def Zaatsu(a):
      a.sort()
      now = a[0][0]
      od = 0
      for i in range(n):
          if now == a[i][0]:
              a[i][0] = od
          else:
              now = a[i][0]
              od += 1
              a[i][0] = od
  
      a.sort(key=lambda x: x[1])
      return a
  
  
  class UnionFind:
      def __init__(self, n):
          self.par = [i for i in range(n + 1)]
          self.rank = [0] * (n + 1)
  
      # 検索
      def find(self, x):
          if self.par[x] == x:
              return x
          else:
              self.par[x] = self.find(self.par[x])
              return self.par[x]
  
      # 併合
      def union(self, x, y):
          x = self.find(x)
          y = self.find(y)
          if self.rank[x] < self.rank[y]:
              self.par[x] = y
          else:
              self.par[y] = x
              if self.rank[x] == self.rank[y]:
                  self.rank[x] += 1
  
      # 同じ集合に属するか判定
      def same_check(self, x, y):
          return self.find(x) == self.find(y)
  
  
  """
  def cmb(n, r, p):
      if (r < 0) or (n < r):
          return 0
      r = min(r, n - r)
      return fact[n] * factinv[r] * factinv[n-r] % p
  
  p = 2
  N = 10 ** 6 + 2
  fact = [1, 1]  # fact[n] = (n! mod p)
  factinv = [1, 1]  # factinv[n] = ((n!)^(-1) mod p)
  inv = [0, 1]  # factinv 計算用
  
  for i in range(2, N + 1):
      fact.append((fact[-1] * i) % p)
      inv.append((-inv[p % i] * (p // i)) % p)
      factinv.append((factinv[-1] * inv[-1]) % p)
  
  """
  
  
  def rl(x):
      return range(len(x))
  
  
  # a = list(map(int, input().split()))
  
  #################################################
  #################################################
  #################################################
  #################################################
  
  
  # 22-
  
  n, w = list(map(int, input().split()))
  item = [[] for i in range(4)]
  ww = 0
  for i in range(n):
      temp = list(map(int, input().split()))
      if i == 0:
          ww = temp[0]
      item[temp[0] - ww].append(temp[1])
  
  for i in range(4):
      item[i].sort()
      item[i].reverse()
  
  # print(item)
  ans = 0
  
  sums = [[0], [0], [0], [0]]
  
  for i in range(4):
      for j in rl(item[i]):
          sums[i].append(sums[i][-1] + item[i][j])
  # print(sums)
  
  
  for i1 in range(len(item[0]) + 1):
      for i2 in range(len(item[1]) + 1):
          for i3 in range(len(item[2]) + 1):
              for i4 in range(len(item[3]) + 1):
                  wei = (i1 + i2 + i3 + i4) * ww + i2 + i3 * 2 + i4 * 3
                  if wei <= w:
                      val = sums[0][i1] + sums[1][i2] + sums[2][i3] + sums[3][i4]
                      ans = max(ans, val)
  
  print(ans)
  
problem_description: Statement
  
  You have N items and a bag of strength W. The i-th item has a weight of w_i
  and a value of v_i.
  
  You will select some of the items and put them in the bag. Here, the total
  weight of the selected items needs to be at most W.
  
  Your objective is to maximize the total value of the selected items.
samples: [{"input": "4 6\n    2 1\n    3 4\n    4 10\n    3 4", "output": "11\n    \n\nThe first and third items should be selected.\n\n* * *"}, {"input": "4 6\n    2 1\n    3 7\n    4 10\n    3 6", "output": "13\n    \n\nThe second and fourth items should be selected.\n\n* * *"}, {"input": "4 10\n    1 100\n    1 100\n    1 100\n    1 100", "output": "400\n    \n\nYou can take everything.\n\n* * *"}, {"input": "4 1\n    10 100\n    10 100\n    10 100\n    10 100", "output": "0\n    \n\nYou can take nothing."}]