#include using namespace std; using ll = long long; const int INF = 1e9 + 10; const ll INFL = 4e18; template struct NegativeVector : vector { int offset; NegativeVector(int lo, int hi, T init) { assert(lo <= hi); this->assign(hi - lo + 1, init); offset = -lo; } T& operator[](int i) { assert(i + offset >= 0); return vector::operator[](i + offset); } T operator[](int i) const { assert(i + offset >= 0); return vector::operator[](i + offset); } }; #include using mint = atcoder::modint998244353; int main() { int N, M; cin >> N >> M; vector V(N), W(N); for (int i = 0; i < N; i++) cin >> V[i] >> W[i]; const int mx = 10000; const int hi = max(0, M + mx); vector> dp(N + 1, NegativeVector(-mx, hi, -INFL)); dp[0][0] = 0; for (int i = 0; i < N; i++) { for (int j = -mx; j <= hi; j++) { if (dp[i][j] == -INFL) continue; dp[i + 1][j] = max(dp[i + 1][j], dp[i][j]); if (j + W[i] >= -mx && j + W[i] <= hi) dp[i + 1][j + W[i]] = max(dp[i + 1][j + W[i]], dp[i][j] + V[i]); } } ll vmx = -INFL; for (int i = -mx; i <= M; i++) vmx = max(vmx, dp[N][i]); vector> dp2(N + 1, NegativeVector(-mx, hi, 0)); for (int i = -mx; i <= M; i++) { if (dp[N][i] == vmx) dp2[N][i] = 1; } for (int i = N - 1; i >= 0; i--) { for (int j = -mx; j <= hi; j++) { if (dp[i][j] == dp[i + 1][j]) dp2[i][j] += dp2[i + 1][j]; if (j + W[i] >= -mx && j + W[i] <= hi && dp[i + 1][j + W[i]] == dp[i][j] + V[i]) dp2[i][j] += dp2[i + 1][j + W[i]]; } } cout << vmx << ' ' << dp2[0][0].val() << endl; }