#include #include using namespace std; using namespace atcoder; using ll = long long; constexpr ll mod = 1e9 + 7; constexpr ll INF = (1LL << 62) - (1LL << 31) - 1; #define REP(i, init, n) for(int i = (int)(init); i < (int)(n); i++) #define RREP(i, init, n) for(int i = (int)(init); i >= (int)(n); i--) #define All(A) A.begin(), A.end() #define rAll(A) A.rbegin(), A.rend() #define vi vector #define vl vector #define vvi vector> #define vvl vector> #define pint pair #define plong pair int N, W; vector P; void solve() { long ans = 0; long tmp_max_val = 0, tmp_idx = -1, max_count = 0; REP(i, 0, N) { long count = (long)(W - 20000) / P[i].second; long tmp_val = count * P[i].first; if(tmp_max_val < tmp_val) { tmp_max_val = tmp_val; tmp_idx = i; max_count = count; } } // cerr << tmp_max_val << " " << tmp_idx << " " << max_count << endl; if(tmp_idx != -1) { ans += P[tmp_idx].first * max_count; W -= P[tmp_idx].second * max_count; } vvl dp(N + 1, vl(W + 1, -1)); dp[0][W] = 0; REP(i, 0, N) { long pv = P[i].first; long pw = P[i].second; RREP(w, W, 0) { if(dp[i][w] != -1) { dp[i + 1][w] = max(dp[i + 1][w], dp[i][w]); } if(w + pw <= W && dp[i][w + pw] != -1) { dp[i + 1][w] = max(dp[i + 1][w], dp[i][w + pw] + pv); } if(w + pw <= W && dp[i + 1][w + pw] != -1) { dp[i + 1][w] = max(dp[i + 1][w], dp[i + 1][w + pw] + pv); } } } /* REP(i, 0, N + 1) { REP(j, 0, W + 1) { cerr << dp[i][j] << " "; } cerr << endl; } */ long max_table = 0; REP(i, 0, N + 1) { REP(j, 0, W + 1) { max_table = max(max_table, dp[i][j]); } } ans += max_table; cout << ans << endl; } int main() { cin.tie(nullptr); ios::sync_with_stdio(false); cin >> N >> W; P.resize(N); REP(i, 0, N) { cin >> P[i].first >> P[i].second; } solve(); }