题解:洛谷 P15256 [USACO26JAN2] Purchasing Milk B
【题目来源】
洛谷:[P15256 USACO26JAN2] Purchasing Milk B - 洛谷
【题目描述】
在国家牛奶日,农夫约翰正在提供桶装牛奶的独家优惠!他有 \(N\)(\(1 \leq N \leq 10^5\))个交易,编号从 \(1\) 到 \(N\)。对于第 \(i\) 个交易,他以 \(a_i\)(\(1 \leq a_i \leq 10^9\),\(a_i < a_{i+1}\))牛币的价格提供 \(2^{i-1}\) 桶牛奶。同一个交易可以被购买任意非负整数次。
你正在考虑 \(Q\)(\(1 \leq Q \leq 10^4\))个独立的询问。对于每个询问,你心中有一个整数 \(x\)(\(1 \leq x \leq 10^9\)),你想知道购买至少 \(x\) 桶牛奶的最小成本。
【输入】
第一行包含两个整数 \(N\) 和 \(Q\)。
接下来的一行包含 \(a_1, a_2, \ldots, a_N\)。
接下来的 \(Q\) 行,每行包含一个整数 \(x\),表示一个询问。
【输出】
对于每个询问,在新的一行输出最小成本。
注意:本题中可能涉及大整数,需要使用 64 位整数数据类型(例如,C/C++ 中的 long long)。
【输入样例】
2 4
10 15
1
2
6
7
【输出样例】
10
15
45
55
【代码详解】
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 100005;
int n, q, ans, sum, minn = 1e18, x; // n: 物品数, q: 查询数, x: 查询目标
int a[N]; // 物品价格
signed main()
{
cin >> n >> q; // 输入物品数和查询数
for (int i = 1; i <= n; i++) // 输入物品价格
{
cin >> a[i];
}
for (int i = 2; i <= n; i++) // 预处理价格
{
a[i] = min(a[i], 2 * a[i - 1]); // 确保价格合理
if (i >= 32) // 只考虑i≥32的情况
{
minn = min(minn, a[i]); // 记录最小价格
}
}
while (q--) // 处理查询
{
cin >> x; // 输入目标数量
ans = minn; // 初始答案
sum = 0; // 当前花费
for (int i = min(31LL, n); i >= 1; i--) // 从大到小处理
{
int base = pow(2, i - 1); // 2^(i-1)
sum += a[i] * (x / base); // 用第i个物品填充
int t = sum;
if (x % base) // 如果还有剩余
{
t += a[i]; // 多买一个
}
ans = min(ans, t); // 更新最小花费
x %= base; // 更新剩余需求
}
cout << ans << endl; // 输出答案
}
return 0;
}
【运行结果】
2 4
10 15
1
10
2
15
6
45
7
55
浙公网安备 33010602011771号