题解:洛谷 P14974 Chip Exchange
【题目来源】
洛谷:P14974 [USACO26JAN1] Chip Exchange B - 洛谷
【题目描述】
奶牛 Bessie 拥有 \(A\) 个 A 型芯片和 \(B\) 个 B 型芯片(\(0\le A,B\le 10^9\))。她可以按意愿多次执行以下操作:
- 如果你至少有 \(c_B\) 个 B 型芯片,则可以用 \(c_B\) 个 B 型芯片交换 \(c_A\) 个 A 型芯片(\(1\le c_A,c_B\le 10^9\))。
请你确定一个最小的非负整数 \(x\),使得以下条件成立:在收到 \(x\) 个额外的随机芯片后,可以保证 Bessie 最终能够拥有至少 \(f_A\) 个 A 型芯片(\(0\le f_A\le 10^9\))。
【输入】
第一行包含 \(T\),表示独立测试用例的数量(\(1\le T\le 10^4\))。
接下来是 \(T\) 个测试用例,每个用例由五个整数 \(A\)、\(B\)、\(c_A\)、\(c_B\)、\(f_A\) 组成。
【输出】
每个测试用例的答案输出在单独的一行。
注意:本题涉及的大整数可能需要使用 64 位整数数据类型(例如,C/C++ 中的 "long long")。
【输入样例】
2
2 3 1 1 6
2 3 1 1 4
【输出样例】
1
0
【核心思想】
-
问题分析:给定 \(A\) 个 A 芯片、\(B\) 个 B 芯片,可用 \(c_B\) 个 B 换 \(c_A\) 个 A。求最小非负整数 \(x\),使得收到 \(x\) 个额外随机芯片后,能保证最终拥有至少 \(f_A\) 个 A 芯片。这是一个数学分析 + 分类讨论问题,关键在于分析转换效率 \(c_A\) 与 \(c_B\) 的关系,以及最坏情况下额外芯片的分配。
-
算法选择:
- 数学推导:先尽可能用现有 B 换 A,然后根据 \(c_A\) 与 \(c_B\) 的大小关系分类讨论
- 最坏情况假设:额外 \(x\) 个芯片都是最坏分配(即最不利于达成目标的分配),需要保证即使最坏也能达成
-
关键步骤:
- 初始转换:
a += b / cb * ca,b %= cb(先用尽现有 B) - 已达目标:若
a >= fa,输出 \(0\) - 转换效率高(\(c_A \geq c_B\)):
- 最坏情况:额外芯片全是 B(因为 B 可以换 A,且效率高)
- 需要补足 A 缺口
fa - a,同时需要cb - b个 B 完成一次转换 numa = fa - a - 1(需要补足的 A,减1是因为可以借位)numb = cb - b(完成一次转换需要的 B)- 答案 =
numa + numb
- 转换效率低(\(c_A < c_B\)):
- 最坏情况:额外芯片全是 A 或混合,需要精确计算
numa = (fa - a - 1) % ca(无法通过完整转换获得的 A 缺口)numb = ceil((fa - a - numa) / ca) * cb - b(完成所需转换次数的 B 缺口)- 答案 =
numa + numb
- 初始转换:
-
时间/空间复杂度:
- 时间复杂度:\(O(T)\),每个测试用例 \(O(1)\) 计算
- 空间复杂度:\(O(1)\),常数变量
-
数学分类讨论的核心思想:
- 最坏情况保证:题目要求"保证"能达成目标,因此必须考虑额外 \(x\) 个芯片的最坏分配(全是对目标最不利的类型)
- 转换效率决定策略:
- \(c_A \geq c_B\):B 换 A 划算,最坏情况是额外芯片全是 A(因为 A 不能直接换 B,但 B 可以换 A)。实际上最坏是缺少 B 来完成转换,因此需要补足 B 缺口和 A 缺口
- \(c_A < c_B\):B 换 A 不划算,最坏情况是额外芯片全是 B(因为需要更多 B 才能换到足够 A)
- 取模与上取整:精确计算转换次数和余数,避免浮点误差
- 适用于"资源转换 + 最坏情况保证"的数学问题,核心在于分类讨论和精确计算
【解题思路】

【算法标签】
普及 #数学
【代码详解】
#include <bits/stdc++.h>
using namespace std;
#define int long long // 将int定义为long long类型,避免大数溢出
int t, a, b, ca, cb, fa; // t: 测试用例数量,a: 当前资源A数量,b: 当前资源B数量,ca: 每次转换获得的A数量,cb: 每次转换需要的B数量,fa: 目标A资源数量
signed main() // 使用signed main()替代int main(),因为int被重定义为long long
{
cin >> t; // 读入测试用例数量
while (t--) // 处理每个测试用例
{
cin >> a >> b >> ca >> cb >> fa; // 读入当前资源情况和目标
int ans = 0; // 初始化答案变量(未使用)
// 先将现有的B资源尽可能转换为A资源
// 计算可转换的次数:b / cb
// 每次转换获得ca个A资源
a += b / cb * ca;
// 剩余不足一次转换的B资源
b %= cb;
// 如果转换后A资源已达到或超过目标
if (a >= fa)
{
cout << 0 << endl; // 无需额外操作
}
// 如果每次转换获得的A数量 >= 需要的B数量(转换效率高或相等)
else if (ca >= cb)
{
// 需要额外获得的A资源数量
int numa = fa - a - 1;
// 需要额外获得的B资源数量(补足到下一次转换)
int numb = cb - b;
// 总成本为两者之和
cout << numa + numb << endl;
}
// 如果每次转换获得的A数量 < 需要的B数量(转换效率低)
else if (ca < cb)
{
// 需要额外获得的A资源数量(取模,表示无法通过完整转换获得的部分)
int numa = (fa - a - 1) % ca;
// 计算需要完整转换的次数,并转换为需要的B资源数量
int numb = ceil(1.0 * (fa - a - numa) / ca) * cb - b;
// 总成本为两者之和
cout << numa + numb << endl;
}
}
return 0;
}
【运行结果】
2
2 3 1 1 6
1
2 3 1 1 4
0
浙公网安备 33010602011771号