#include using namespace std; typedef long long ll; const ll INF = 4e18; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N; cin >> N; vector c(N + 1); vector v(N + 1); for (int i = 1; i <= N; ++i) { cin >> c[i] >> v[i]; } // 重量 >= 2 的物品最多选 N/2 个 int MAX_M = N / 2 + 1; vector> dp(MAX_M, vector(N + 1, -INF)); dp[0][0] = 0; // 处理重量 >= 2 的物品:二进制拆分 + 0/1 背包 for (int i = 2; i <= N; ++i) { if (c[i] == 0) continue; int cnt = min(c[i], N / i); // 最多能选 N/i 个 int power = 1; while (cnt > 0) { int take = min(power, cnt); int weight = i * take; ll value = (ll)take * v[i]; int m_min = take; int m_max = min(MAX_M - 1, (N - weight) / 2 + take); if (m_min > m_max) { cnt -= take; power <<= 1; continue; } // 0/1 背包转移 for (int m = m_max; m >= m_min; --m) { int w_min = weight + 2 * (m - take); for (int w = N; w >= w_min; --w) { if (dp[m - take][w - weight] != -INF) { ll val = dp[m - take][w - weight] + value; if (val > dp[m][w]) dp[m][w] = val; } } } cnt -= take; power <<= 1; } } // 合并重量为 1 的物品 ll v1 = v[1]; // pref[m][W] = max_{w <= W} (dp[m][w] - m * v1) vector> pref(MAX_M, vector(N + 1, -INF)); for (int m = 0; m < MAX_M; ++m) { ll cur_max = -INF; for (int w = 0; w <= N; ++w) { if (dp[m][w] != -INF) { ll val = dp[m][w] - (ll)m * v1; if (val > cur_max) cur_max = val; } pref[m][w] = cur_max; } } // 计算每个 k 的答案 for (int k = 1; k <= N; ++k) { ll ans = -INF; int max_m = min(k, MAX_M - 1); for (int m = 0; m <= max_m; ++m) { int W = N - k + m; if (W >= 0 && W <= N) { if (pref[m][W] != -INF) { ll val = pref[m][W] + (ll)k * v1; if (val > ans) ans = val; } } } cout << ans << '\n'; } return 0; }