洛谷传送门
注意到题目要求我们计算出最多能买多少个纪念品,所以容易想到二分。
我们二分最多能买多少个纪念品,把每个纪念品的实际花费计算出来,从小到大排个序,取出前 \(mid\) 个,判断花费是否合法即可。
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int N = 1e5 + 10; int n, s, cnt, ans, res; int a[N], b[N]; inline bool check(int mid){ for(int i = 1; i <= n; i++) b[i] = a[i] + i * mid;//计算每个物品的实际花费。 sort(b + 1, b + 1 + n); res = 0; for(int i = 1; i <= mid && res <= s; i++)//取前 k 个物品,总花费小于等于 s res += b[i]; return res <= s; } int main(){ scanf("%d%d", &n, &s); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); int l = 0, r = n; while(l <= r){ int mid = (l + r) >> 1; if(check(mid)) cnt = mid, ans = res, l = mid + 1;//二分边界向来不好调,合法时直接更新答案即可。 else r = mid - 1; } printf("%d %d\n", cnt, ans); return 0; }