1 条题解
-
0
📝 题目大意
给定两个整数 ,每次操作将较大的数减去较小的数(若 则 ,否则 ),求使 所需的最少操作次数。
💡 解题思路
-
题目分析:直接模拟每次减一次会超时,因为 最大可达 ,最坏情况(如 )需要 次操作。需要批量处理连续的减法操作。
-
算法推导:
- 本题本质是辗转相减法求 GCD 的过程,操作次数即辗转相减的步数。
- 当 时,我们可以连续减去多个 ,直到 。设 ,表示在 仍大于 的前提下最多能减多少次 ——减完 次后 要么小于 ,要么等于 (此时循环终止)。
- 将 累加到答案
ans中,然后更新 。 - 对称地,当 时,,
ans += k,。 - 循环直到 ,输出
ans。 - 之所以用 而非 ,是因为 在 是 的倍数时会多减一次导致 变为 (例如 , 会直接让 跳过 的状态),而 保证减完后 。
-
边界与细节:
- 初始 时,操作次数为 ,循环不进入,直接输出 。
- 代码中的
if (A == 0 || B == 0) break;是防御性写法,正常情况下正整数输入不会出现 。 - 变量使用
long long(64 位整数),因为 且答案可能很大(最大约 级别)。
⏱️ 复杂度分析
- 时间复杂度:,与辗转相除法(欧几里得算法)同阶,每次批量减法相当于一次取模运算。
- 空间复杂度:,仅使用常数个变量。
💻 标准代码 (C++)
#include <iostream> using namespace std; int main() { long long A, B; cin >> A >> B; long long ans = 0; while (A != B) { // 防御性判断:若出现 0 则退出(正常情况不会到达) if (A == 0 || B == 0) break; if (A > B) { // 计算 A 可以连续减去多少个 B(保证减完后 A > 0) long long k = (A - 1) / B; ans += k; // 累加操作次数 A -= k * B; // 批量减去 k 个 B } else { // 对称处理 B > A 的情况 long long k = (B - 1) / A; ans += k; B -= k * A; } } cout << ans << endl; return 0; } -
- 1
信息
- ID
- 704
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- (无)
- 递交数
- 5
- 已通过
- 3
- 上传者