import std.stdio, std.string, std.range, std.algorithm, std.math, std.typecons, std.conv;

long[] weights, values;
long N;
long W;
long w0;
long[][][] memo;
void main() {
  auto inp = readln.split.to!(long[]);
  N = inp[0];
  W = inp[1];
  weights = new long[N];
  values = new long[N];
  foreach (i; 0..N) {
    inp = readln.split.to!(long[]);
    auto w = inp[0], v = inp[1];
    weights[i] = w;
    values[i] = v;
  }
  w0 = weights[0];
  foreach (i; 0..N) {
    weights[i] -= w0;
  }
  memo = new long[][][](N,weights.sum+1,N);
  func(0, 0, 0).writeln;
}

long func(int i, long w, int count) {
  if (i == N) return 0;
  if (memo[i][w][count] > 0) return memo[i][w][count];
  auto cand1 = func(i+1, w, count);
  if (w + weights[i] > W - (count+1) * w0) return memo[i][w][count] = cand1;
  auto cand2 = func(i+1, w + weights[i], count+1) + values[i];
  return memo[i][w][count] = max(cand1, cand2);
}
