import java.util.*

fun solve(n:Int, w:Int, wv:Array<Pair<Long, Long>>){
    val w0 = wv[0].first
    //val dp = Array(n+1,n+1,4 *(n+1)){0}
    val dp = Array(n + 1) {
        Array(n + 1) {
            Array(4 * (n + 1)) { -1L }
        }
    }
    dp[0][0][0] = 0
    dp[0][1][0] = wv[0].second
    for (i in 1 until n) {
        for (c in 0..n) {
            for (d in 0 until 4 * (n + 1)) {
                if (c - 1 >= 0 && d - (wv[i].first - w0) >= 0) {
                    dp[i][c][d] = Math.max(dp[i - 1][c][d], dp[i - 1][c - 1][d - (wv[i].first - w0).toInt()] + wv[i].second)
                } else {
                    dp[i][c][d] = dp[i - 1][c][d]
                }


            }
        }
    }

    for (i in 0 until n) {
        for (c in 0..n) {
            for (d in 0 until 4 * (n + 1)) {
                print(dp[i][c][d].toString() + " ")
            }
            println()
        }
        println()
    }

    // Wいか
    val result = (0 .. n).map{c ->
        (0 until 4 *(n+1)).map{d->
            Pair(c * w0 + d, dp[n-1][c][d])
        }
    }.flatten().filter{
        it.first <= w
    }.map{it.second}.max()
    println(result)
}

fun solve2(n:Int, w:Int, wv:Array<Pair<Long, Long>>){
    val w0 = wv[0].first
    //val dp = Array(n+1,n+1,4 *(n+1)){0}
    val dp = Array(n + 1) {
        //    Array(4 * (n + 1)) { Int.MIN_VALUE.toLong() }
        Array(4 * (n + 1)) { -1L }

    }

    val nextDP = Array(n + 1) {
        //    Array(4 * (n + 1)) { Int.MIN_VALUE.toLong() }
        Array(4 * (n + 1)) { -1L }

    }

    dp[0][0] = 0
    dp[1][0] = wv[0].second
    for (i in 1 until n) {
        for (c in 0..n) {
            for (d in 0 until 4 * (n + 1)) {
                if (c - 1 >= 0 && d - (wv[i].first - w0) >= 0) {
                    nextDP[c][d] = Math.max(dp[c][d], dp[c - 1][d - (wv[i].first - w0).toInt()] + wv[i].second)
                } else {
                    nextDP[c][d] = dp[c][d]
                }
            }
        }
        for (c in 0..n) {
            for (d in 0 until 4 * (n + 1)) {
                dp[c][d] = nextDP[c][d]
            }
        }


    }

    /*
    for (i in 0 until n) {
        for (c in 0..n) {
            for (d in 0 until 4 * (n + 1)) {
                print(dp[i][c][d].toString() + " ")
            }
            println()
        }
        println()
    }

     */
    // Wいか
    val result = (0 .. n).map{c ->
        (0 until 4 *(n+1)).map{d->
            Pair(c * w0 + d, dp[c][d])
        }
    }.flatten().filter{
        it.first <= w
    }.map{it.second}.max()
    println(result)
}


fun main(args: Array<String>) {
    val (n, w) = readLine()!!.split(' ').map(String::toInt)
    val wv = Array(n) {
        val (w0, v0) = readLine()!!.split(' ').map(String::toLong)
        Pair(w0, v0)
    }
    solve2(n,w,wv)
}