import java.io.{BufferedReader, InputStream, InputStreamReader}
import java.util.StringTokenizer

import scala.collection.mutable
import scala.util.Sorting
import math.{abs, max, min}

object Main {
  def solve(): Unit = {
    val sc = new InputReader(System.in)
    val N = sc.nextInt()
    val W = sc.nextInt()
    val w = Array.ofDim[Int](N + 1)
    val v = Array.ofDim[Int](N + 1)
    val w1 = sc.nextInt()
    v(1) = sc.nextInt()
    (2 to N) foreach { i =>
      w(i) = sc.nextInt() - w1
      v(i) = sc.nextInt()
    }

    val dp = Array.ofDim[Int](N + 1, 301 * 100 + 300 + 1)
    for {
      i <- 1 to N
      j <- 0 to 3 * i
      jj <- 0 to i
    } {
      val k = jj * 301 + j
      val pre_v = k - w(i) - 301
      dp(i)(k) =
        if (pre_v >= 0) max(dp(i - 1)(pre_v) + v(i), dp(i -1)(k))
        else dp(i -1)(k)
    }
    val (ans, _) = (dp(N).zipWithIndex filter { case (_, k) =>
      k % 301 + k / 301 * w1 <= W
    }).maxBy(_._1)
    println(ans)
  }

  def main(args: Array[String]): Unit = {
    solve()
  }



  private class InputReader(val stream: InputStream) {
    private val reader = new BufferedReader(new InputStreamReader(stream), 32768)
    private var tokenizer: StringTokenizer = null

    def next: String = {
      while (tokenizer == null || !tokenizer.hasMoreTokens)
        tokenizer = new StringTokenizer(reader.readLine)
      tokenizer.nextToken
    }

    def nextInt(): Int = next.toInt
    def nextLong(): Long = next.toLong
    def nextChar(): Char = next.charAt(0)
  }

}
