Bouquet (Hard Version)§
该题可转化为:分别给出
a和a + 1的个数,请求出用这些数字的和凑出的最大的小于m的值。我们可以先放
a,之后再放a + 1。显然如果和小于
m意味着我们还有多余的硬币。可以发现,如果此时还有
a + 1可以通过将原本放进去的a置换出来,就能多花1硬币。注意,能提供置换多花的硬币是由剩余的硬币,
a + 1的剩余数量,放入的a的数量所制约的。#include <bits/stdc++.h> using i64 = long long; void solve() { i64 n, m; std::cin >> n >> m; std::vector<i64> a(n), c(n); std::map<i64, i64> cnt; for (auto &it : a) { std::cin >> it; } for (int i = 0; i < n; i++) { std::cin >> c[i]; cnt[a[i]] += c[i]; } i64 ans = 0; for (auto it : a) { i64 _m = m; i64 c1 = std::min(_m / it, cnt[it]); i64 mid = c1 * it; _m -= c1 * it; i64 c2 = std::min(_m / (it + 1), cnt[it + 1]); mid += c2 * (it + 1); _m -= c2 * (it + 1); mid += std::min({cnt[it + 1] - c2, _m, c1}); ans = std::max(ans, mid); } std::cout << ans << '\n'; } int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int t; std::cin >> t; while (t--) { solve(); } return 0; }