import std.stdio, std.math, std.algorithm, std.array, std.string, std.conv, std.container, std.range;
T Read(T)() { return readln.chomp.to!(T); }
T[] Reads(T)() { return readln.split.to!(T[]); }
alias read = Read!(int);
alias reads = Reads!(int);

int n, W;
int[] w;
int[] v;

long[][] dp = new long[][](114, 100010);
long rec(int i, int j) {
    if (i == n)
        return 0;
    if (dp[i][j] >= 0)
        return dp[i][j];
    if (j + w[i] <= W)
        return dp[i][j] = max(rec(i+1, j), rec(i+1, j + w[i]) + v[i]);
    else
        return dp[i][j] = rec(i+1, j);
}

void main() {
    readf("%d %d\n", &n, &W);
    w.length = v.length = n;
    foreach (i ; 0..n) {
        readf("%d %d\n", &w[i], &v[i]);
    }
    foreach (r ; dp) fill(r, -1);
    writeln(rec(0, 0));
}
