void main()
{
    long[] tmp = rdRow;
    long n = tmp[0], w = tmp[1];

    long[][] items = new long[][](4);
    tmp = rdRow;
    long w0 = tmp[0];
    items[0] ~= tmp[1];
    foreach (i; 0 .. n-1)
    {
        tmp = rdRow;
        long wi = tmp[0] - w0, v = tmp[1];
        items[wi] ~= v;
    }

    foreach (i; 0 .. 4)
    {
        items[i].sort!"a > b";
    }

    long[] len = new long[4];
    long[][] total = new long[][](4);
    foreach (i; 0 .. 4)
    {
        total[i].length = items[i].length + 1;
        len[i] = total[i].length;
        foreach (j; 0 .. items[i].length)
        {
            total[i][j+1] = total[i][j] + items[i][j];
        }
    }

    long result;
    foreach (i; 0 .. len[0])
    {
        long w1 = w0 * i;
        if (w1 > w) break;

        long v1 = total[0][i];

        foreach (j; 0 .. len[1])
        {
            long w2 = w1 + (w0 + 1) * j;
            if (w2 > w) break;

            long v2 = v1 + total[1][j];

            foreach (k; 0 .. len[2])
            {
                long w3 = w2 + (w0 + 2) * k;
                if (w3 > w) break;

                long v3 = v2 + total[2][k];

                foreach (l; 0 .. len[3])
                {
                    long w4 = w3 + (w0 + 3) * l;
                    if (w4 > w) break;

                    long v4 = v3 + total[3][l];

                    result = max(result, v4);
                }
            }
        }
    }

    result.writeln;
}

enum long mod = 10^^9 + 7;
enum long inf = 1L << 60;

T rdElem(T = long)()
if (!is(T == struct))
{
    return readln.chomp.to!T;
}

alias rdStr = rdElem!string;
alias rdDchar = rdElem!(dchar[]);

T rdElem(T)()
if (is(T == struct))
{
    T result;
    string[] input = rdRow!string;
    assert(T.tupleof.length == input.length);
    foreach (i, ref x; result.tupleof)
    {
        x = input[i].to!(typeof(x));
    }
    return result;
}

T[] rdRow(T = long)()
{
    return readln.split.to!(T[]);
}

T[] rdCol(T = long)(long col)
{
    return iota(col).map!(x => rdElem!T).array;
}

T[][] rdMat(T = long)(long col)
{
    return iota(col).map!(x => rdRow!T).array;
}

void wrMat(T = long)(T[][] mat)
{
    foreach (row; mat)
    {
        foreach (j, compo; row)
        {
            compo.write;
            if (j == row.length - 1) writeln;
            else " ".write;
        }
    }
}

import std.stdio;
import std.string;
import std.array;
import std.conv;
import std.algorithm;
import std.range;
import std.math;
import std.numeric;
import std.traits;
import std.container;
import std.functional;
import std.typecons;
import std.ascii;
import std.uni;