//  [cpp]
#include <algorithm>
#include <cstdio>
#include <vector>

typedef long long int ll;

struct state {
    ll aw;
    ll av;
    state(ll aw = 0, ll av = 0) : aw(aw), av(av) {}
};

struct item {
    int w;
    int v;
    double d;
    item(int w, int v) : w(w), v(v), d((double)v / w) {}
};

int n, w;

ll lower;

std::vector<item> is;
std::vector<state> dp[2];

void add(const std::vector<state> &s, const item &k, std::vector<state> &u,
         ll uw) {
    auto i = s.cbegin();
    auto j = s.cbegin();
    while (i != s.cend() && j != s.cend()) {
        if (i->aw > uw) {
            i = s.cend();
            break;
        }
        ll jav = j->av + k.v;
        ll jaw = j->aw + k.w;
        if (jaw > uw) {
            j = s.cend();
            break;
        }
        if (i->aw <= jaw && i->av >= jav) {
            ++j;
        } else if (i->aw >= jaw && i->av <= jav) {
            ++i;
        } else if (i->aw < jaw) {
            u.push_back(*i++);
        } else {
            u.emplace_back(state(jaw, jav));
            ++j;
        }
    }
    while (i != s.cend()) {
        if (i->aw > uw)
            return;
        u.push_back(*i++);
    }
    while (j != s.cend()) {
        ll jav = j->av + k.v;
        ll jaw = j->aw + k.w;
        if (jaw > uw)
            return;
        u.emplace_back(state(jaw, jav));
        ++j;
    }
}

void remove(const std::vector<state> &s, const item &k, std::vector<state> &u,
            ll uw) {
    auto i = s.cbegin();
    auto j = s.cbegin();
    while (i != s.cend() && j != s.cend()) {
        if (i->aw > uw) {
            i = s.cend();
            break;
        }
        ll jav = j->av - k.v;
        ll jaw = j->aw - k.w;
        if (jaw > uw) {
            j = s.cend();
            break;
        }
        if (i->aw <= jaw && i->av >= jav) {
            ++j;
        } else if (i->aw >= jaw && i->av <= jav) {
            ++i;
        } else if (i->aw < jaw) {
            u.push_back(*i++);
        } else {
            u.emplace_back(state(jaw, jav));
            ++j;
        }
    }
    while (i != s.cend()) {
        if (i->aw > uw)
            return;
        u.push_back(*i++);
    }
    while (j != s.cend()) {
        ll jav = j->av - k.v;
        ll jaw = j->aw - k.w;
        if (jaw > uw)
            return;
        u.emplace_back(state(jaw, jav));
        ++j;
    }
}

ll upper;

inline void shrink(const std::vector<state> &s, double d0, double d1,
                   std::vector<state> &u) {
    for (auto x : s) {
        ll t = (x.aw > w) ? x.av - (x.aw - w) * d0 : x.av + (w - x.aw) * d1;
        if (t >= lower)
            u.push_back(x);
        if (t > upper)
            upper = t;
    }
}

int main() {
    scanf("%d%d", &n, &w);
    is.reserve(200);
    dp[0].reserve(300);
    dp[1].reserve(300);

    is.emplace_back(item(1, 0));

    for (int i = 0; i < n; i++) {
        int ww, vv;
        scanf("%d%d", &ww, &vv);
        if (ww <= w)
            is.emplace_back(item(ww, vv));
    }
    n = is.size() - 1;

    std::sort(is.begin() + 1, is.end(),
              [](const item &x, const item &y) { return x.d > y.d; });
    is.emplace_back(item(1, 0));

    ll aw = 0;
    ll av = 0;
    int ii;
    for (ii = 1; ii <= n; ii++) {
        const item &x = is[ii];
        if (aw + x.w > w)
            break;
        aw += x.w;
        av += x.v;
    }

    dp[0].emplace_back(state(aw, av));

    lower = av;
    ll sumw = w + aw;

    for (int i = ii - 1, j = ii; i > 0 || j <= n;) {
        if (i > 0) {
            sumw -= is[i].w;
            remove(dp[0], is[i], dp[1], sumw);
            dp[0].resize(0);
            lower = (std::upper_bound(
                         dp[1].cbegin(), dp[1].cend(), w,
                         [](int w, const state &x) { return x.aw > w; }) -
                     1)
                        ->av;
            shrink(dp[1], is[i - 1].d, is[j].d, dp[0]);
            dp[1].resize(0);
            --i;
        }

        if (j <= n) {
            add(dp[0], is[j], dp[1], sumw);
            dp[0].resize(0);
            lower = (std::upper_bound(
                         dp[1].cbegin(), dp[1].cend(), w,
                         [](int w, const state &x) { return x.aw > w; }) -
                     1)
                        ->av;
            shrink(dp[1], is[i].d, is[j + 1].d, dp[0]);
            dp[1].resize(0);
            ++j;
        }
        if (lower == upper)
            break;
    }

    lower = (std::upper_bound(dp[0].cbegin(), dp[0].cend(), w,
                              [](int w, const state &x) { return x.aw > w; }) -
             1)
                ->av;
    printf("%lld\n", lower);

    return 0;
}