辗转相除法与裴蜀定理

2/15/2023

# 辗转相除法与裴蜀定理

# 1、 辗转相除法

​ 关于辗转相除法求最大公约数在算法题中也算常见,但是笔者一直是在记公式,这就导致了长时间不接触相关题目后很难流畅写出求最大公约数的代码,此次笔者记录下辗转相除法的推导与证明。

​ 记 d 为 正整数 a 和 正整数 b 的最大公因数,记 a = k * b + r (假设a > b),则r = a - k * b,因为d可以整除 a b,即a b都是d的倍数,那么 r 也一定是 d 的倍数,那么 a 和 b的最大公因数 一定等于 b 和 r 的最大公因数,即gcd(a,b) = gcd(b, a % b)。此时我们会疑惑 在递归过程中我们并不知道 a b 之间的大小关系,假设a < b 那么 gcd(a,b) == gcd (b,a % b) = gcd(b,a) ,故无须纠结于a,b的大小关系,当 b = 0 时,递归结束,此时的a值即为答案。

​ 代码实现如下:

int gcd(int a,int b)
{
    return b == 0 ? a : gcd(b, a % b);
}
1
2
3
4

# 2、 裴蜀定理

​ 关于裴蜀定理:

对于不全为0的任意整数,记 g = gcd(a,b), 则对于任意整数 x 和 y都满足 a * x + b * y 为 g 的倍数,特别地,存在x y满足a * x + b * y = g

​ 裴蜀定理也可以推广到n个整数:

a1 a2 ... an的最大公约数为 g ,则对于任意n个整数x1 x2 ... xn 分别与a1 a2 ..... an的乘积和一定是g的倍数,且存在这样的n个数,其与a1 a2 ... an的乘积和为 g

由此可到一推论:a1 a2 .... an的最大公因数为g的充分必要条件为 存在x1 x2 ... xna1 a2 ... an的乘积和为 g

​ 例题:

检查好数组 (opens new window)

​ 代码:

class Solution {
public:
    int gcd(int a,int b)
    {
        return b == 0 ? a : gcd(b, a % b);
    }
    bool isGoodArray(vector<int>& nums) {
        // 裴蜀定理 判断所有数的最大公约数是否为1即可
        int ans = 0;
        for(int x : nums) ans = gcd(x, ans);
        return ans == 1;
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13