题解:洛谷 AT_abc460_a Mod While Positive

【题目来源】

洛谷:AT_abc460_a [ABC460A] Mod While Positive - 洛谷

【题目描述】

给定正整数 \(N\)\(M\)
\(M\not=0\) 时,重复执行以下操作,请计算出操作进行的次数:

  • \(x\)\(N\) 除以 \(M\) 的余数。将 \(M\) 的值替换为 \(x\)

注:可以证明,经过有限次上述操作后,必定会使 \(M=0\)

【输入】

从标准输入按以下形式给出数据:

\(N\) \(M\)

【输出】

输出答案。

【输入样例】

8 5

【输出样例】

3

【核心思想】

  1. 问题分析:给定正整数 \(N\)\(M\),模拟辗转相除的过程:不断用 \(N \bmod M\) 替换 \(M\),直到 \(M = 0\),统计操作次数。这是一个辗转相除法(欧几里得算法)的模拟问题,核心在于理解操作序列并正确计数。

  2. 算法选择

    • 直接模拟:用循环执行取模替换操作,直到 \(M = 0\)
  3. 关键步骤

    • 读入数据\(N, M\)
    • 循环执行(当 \(M \neq 0\)):
      • \(x \leftarrow N \bmod M\)
      • \(N \leftarrow M\)\(M \leftarrow x\)
      • \(ans \leftarrow ans + 1\)
    • 输出结果\(ans\)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(\log \min(N, M))\),辗转相除法的步数上界
    • 空间复杂度:\(O(1)\)
  5. 辗转相除模拟的核心思想

    • 操作序列的理解:每次操作为 \(M \leftarrow N \bmod M\),同时 \(N\) 更新为原来的 \(M\)。这与标准欧几里得算法 \(\gcd(N, M) = \gcd(M, N \bmod M)\) 完全一致,只是额外统计了步数
    • 终止性保证:由于 \(N \bmod M < M\),每次操作后 \(M\) 严格减小,最终必变为 \(0\)
    • 步数计算:循环条件是 \(M \neq 0\),但最后一次操作使 \(M = 0\) 时循环已结束,因此需要额外加 \(1\)。或者更简洁地:循环条件改为 \(M > 0\),每次 \(N \leftarrow M, M \leftarrow N \bmod M\),计数
    • 边界注意:代码中 while (n % m != 0) 的条件判断的是上一次操作后的余数,因此循环内只统计了"非零余数"的次数,最后需要 ans + 1 补上最后一次使 \(M = 0\) 的操作
    • 适用于基础模拟、欧几里得算法理解类入门问题

【算法标签】

入门 #模拟

【代码详解】

#include <bits/stdc++.h>
using namespace std;
int n, m, ans;  // n: 第一个数,m: 第二个数,ans: 步数计数器
int main()
{
    cin >> n >> m;  // 输入两个正整数
    while (n % m != 0)  // 当n不能被m整除时循环
    {
        /// n = n % m;  // 错误的写法,应该是m = n % m
        m = n % m;  // 用n对m取余,更新m
        ans++;  // 步数加1
    }
    cout << ans + 1 << endl;  // 输出总步数
    return 0;
}

【运行结果】

8 5
3
posted @ 2026-08-26 10:12  团爸讲算法  阅读(6)  评论(0)    收藏  举报