求最大公约数问题

GitHub跳转原题关系图返回列表

用辗转相除法求最大公约数:反复把 (a, b) 换成 (b, a mod b),公因数集合始终不变而第二个数严格变小,b 归零时 a 就是答案。

OJ: roj

题目 ID: 1207

难度:普及-

标签:数论gcd辗转相除法python

创建: 2026-09-29 23:37

更新: 2026-10-05 05:32

题目描述

给定两个正整数 a,ba, b(1⩽a,b<1091 \leqslant a, b < 10^9),求它们的最大公约数。一行读入两个正整数,输出一个正整数即为答案。

样例输入:6 9,样例输出:3。

思路

用辗转相除法:循环把 (a,b)(a, b) 替换为 (b,a mod b)(b, a \bmod b),公因数集合不变而 bb 严格减小;b=0b=0 时直接输出 aa。复杂度 O(log⁡min⁡(a,b))O(\log \min(a, b))。

参考代码

Python 版:

python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-09-29 23:37
# update_at: 2026-09-29 23:41

import sys


def gcd(a: int, b: int) -> int:
    """返回 a 与 b 的最大公约数:反复把 (a, b) 换成 (b, a % b),b 归零时 a 就是答案。"""
    while b:
        a, b = b, a % b  # 余数严格变小,所以循环次数是 O(log min(a, b))
    return a


def solve() -> None:
    """读入一行里的两个正整数,输出它们的最大公约数。"""
    a, b = map(int, sys.stdin.buffer.read().split())
    print(gcd(a, b))


if __name__ == "__main__":
    solve()

C++ 版(同一算法):

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-10-05 05:32
 * update_at: 2026-10-05 05:32
 */
#include <cstdio>

typedef long long ll;

// gcd:辗转相除,反复把 (a, b) 换成 (b, a % b),b 归零时 a 就是答案
ll gcd(ll a, ll b) {
    while (b != 0) {
        ll r = a % b; // 余数严格变小,循环次数为 O(log min(a, b))
        a = b;
        b = r;
    }
    return a;
}

int main() {
    ll a, b;
    if (scanf("%lld %lld", &a, &b) != 2) return 0;
    printf("%lld\n", gcd(a, b));
    return 0;
}