题解:AcWing 872 最大公约数

【题目来源】

AcWing:872 最大公约数 - AcWing题库

【题目描述】

给定 \(n\) 对正整数 \(a_i,b_i\),请你求出每对数的最大公约数。

【输入】

第一行包含整数 \(n\)

接下来 \(n\) 行,每行包含一个整数对 \(a_i,b_i\)

【输出】

输出共 \(n\) 行,每行输出一个整数对的最大公约数。

【输入样例】

2
3 6
4 6

【输出样例】

3
2

【核心思想】

  1. 问题分析:给定 \(n\) 对正整数 \(a_i, b_i\),求每对数的最大公约数(GCD)。最大公约数是能够同时整除两个数的最大正整数。这是一个基础的数论问题,核心在于利用欧几里得算法(辗转相除法)高效求解两数的 GCD。

  2. 算法选择

    • 欧几里得算法(辗转相除法):基于核心定理 \(\gcd(a, b) = \gcd(b, a \bmod b)\),通过不断取余将问题规模缩小,直到余数为 \(0\) 时得到答案
    • 递归实现:代码简洁,直接按照公式递归调用,终止条件为 \(b = 0\)
  3. 关键步骤

    • 读取输入:整数 \(n\),以及 \(n\) 对正整数 \((a_i, b_i)\)
    • 定义 GCD 函数
      • gcd(a, b):若 \(b = 0\) 则返回 \(a\),否则返回 gcd(b, a % b)
    • 处理每组数据
      • 输入 \(a, b\)
      • 调用 gcd(a, b) 计算最大公约数
      • 输出结果
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n \cdot \log(\min(a_i, b_i)))\)。欧几里得算法单次时间复杂度为 \(O(\log(\min(a, b)))\),处理 \(n\) 对数据乘以 \(n\)
    • 空间复杂度:\(O(\log(\min(a_i, b_i)))\),递归栈深度,由欧几里得算法的迭代次数决定
  5. 欧几里得算法的核心思想

    • 核心定理\(\gcd(a, b) = \gcd(b, a \bmod b)\)。若 \(d\)\(a\)\(b\) 的公约数,则 \(d\) 也是 \(b\)\(a \bmod b\) 的公约数;反之亦然。因此两问题的最大公约数相同
    • 规模递减:每次递归都将较大的数替换为两数相除的余数,余数严格小于除数,确保问题规模严格递减,最终必然在有限步内达到 \(b = 0\) 的终止条件
    • 效率保证:对于斐波那契数对,欧几里得算法达到最坏情况,但即便如此迭代次数也仅为 \(O(\log(\min(a, b)))\),效率极高
    • 扩展应用:GCD 是数论的基石,可直接用于计算最小公倍数(\(\text{lcm}(a, b) = a \times b / \gcd(a, b)\)),也是扩展欧几里得算法、中国剩余定理等高级算法的基础
    • 适用于两数最大公约数、最小公倍数、分数约分、模逆元 existence 判断等问题

【算法标签】

欧几里得算法

【代码详解】

#include <bits/stdc++.h>
using namespace std;

int n;  // 输入的计算次数

// 计算两个数的最大公约数(GCD)
int gcd(int a, int b)
{
    // 递归终止条件:当b为0时,a即为最大公约数
    // 否则递归计算gcd(b, a % b)
    return b ? gcd(b, a % b) : a;
}

int main()
{
    // 输入需要计算GCD的次数
    cin >> n;

    // 处理每组输入
    while (n--)
    {
        int a, b;
        cin >> a >> b;  // 输入两个整数

        // 计算并输出它们的最大公约数
        cout << gcd(a, b) << endl;
    }

    return 0;
}

【运行结果】

2
3 6
3
4 6
2
posted @ 2026-06-23 11:23  团爸讲算法  阅读(6)  评论(0)    收藏  举报