import std.algorithm;
import std.array;
import std.ascii;
import std.bigint;
import std.complex;
import std.container;
import std.conv;
import std.functional;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

auto readInts() {
	return array(map!(to!int)(readln().strip().split()));
}
auto readInt() {
	return readInts()[0];
}
auto readLongs() {
	return array(map!(to!long)(readln().strip().split()));
}
auto readLong() {
	return readLongs()[0];
}

void readlnTo(T...)(ref T t) {
    auto s = readln().split();
    assert(s.length == t.length);
    foreach(ref ti; t) {
        ti = s[0].to!(typeof(ti));
        s = s[1..$];
    }
}

const real eps = 1e-10;

const long p = 1_000_000_000 + 7;

void main(){
    long N, W;
    readlnTo(N, W);

    alias T = Tuple!(long, long);
    T[] l;
    foreach(i; iota(N)) {
        auto t = readLongs();
        l ~= tuple(t[0], t[1]);
    }
    auto w1 = l[0][0];
    long[] a = l.filter!(x => x[0] == w1).map!(x => x[1]).array();
    long[] b = l.filter!(x => x[0] == w1 + 1).map!(x => x[1]).array();
    long[] c = l.filter!(x => x[0] == w1 + 2).map!(x => x[1]).array();
    long[] d = l.filter!(x => x[0] == w1 + 3).map!(x => x[1]).array();
    a.sort();
    a.reverse();
    b.sort();
    b.reverse();
    c.sort();
    c.reverse();
    d.sort();
    d.reverse();
    long ans = 0;
    foreach(i; iota(a.length+1)) {
        foreach(j; iota(b.length+1)) {
            foreach(k; iota(c.length+1)) {
                long wl = W - w1*i - (w1+1)*j - (w1+2)*k;
                if(wl < 0) {
                    continue;
                }
                long m = wl / (w1+3);
                ans = max(ans, sum(a.take(i) ~ b.take(j) ~ c.take(k) ~ d.take(m), 0L));
            }
        }
    }
    writeln(ans);
}

