【gcd/辗转相除法】gcd/辗转相除法的证明

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/er111er/article/details/79251895

gcd/辗转相除法的证明

此文仅供蒟蒻参考,dalao请我也不记得是左上角还是右上角了。

前言

这不是小学奥数吗?
数学上来先打表,数论只会gcd。

上面几句话一直打击我学习数论的信心。
不仅只会gcd,连gcd都不会证明,可见我有多菜了。
直到受到某位dalao的指教,我终于证明了gcd。
dalao曰:”数论,数字之理论也。有术曰辗转相除,欲证此术,必先知反对称矣。”
那么问题来了,反对称是什么。

知识储备

下面内容很基础。对于我的证明方法来说,是必须要知道的。

1.整数具有大小(顺序)关系,用≤、≥、<、>、=来表示,其中≤具有反对称性,即:
a b b a   <=>  a = b ( a Z , b Z )
可以说是非常基础的东西了,但是却是证明gcd的关键方法。
2.符号 | 的含义:
b = q a ( a Z , a 0 , q Z , b Z ) ,则称 a b 的约数(或 a 整除 b ),即 b / a 的结果为整数(这里注意区分除和除以的区别),记作: a | b ,符号 a | b 蕴含条件 a 0
3.整除的一个性质:
a | b a | c   =>   a | b x + c y ( x Z , y Z )
这个性质的证明:
a | b b = q 1 a ,由 a | c c = q 2 a ,则 b x + c y = q 1 x a + q 2 y a = a ( q 1 x + q 2 y ) a | b x + c y
4.余数的定义:
对于给定的 a Z , a 0 , b Z ,一定存在唯一的一对 q Z , 0 r < | a | 满足:
b = q a + r
我们称 q b / a 的商,记作 q = [ b / a ] (有时也记作 b / a a 表示对实数a向下取整,即取小于等于a的整数中最大的一个), r b / a 的余数,记作 r = b q a

扯了这么多乱七八糟的东西那么现在开始证明gcd。

gcd证明过程

g c d ( n , m ) 表示 n , m 的最大公约数,
证明: g c d ( n , m ) = g c d ( m , n   m o d   m )
 由 g c d 定义可得,(1)对于任意的 d | n d | m ,都有 g c d ( n , m ) d 。(2) g c d ( n , m ) | n g c d ( n , m ) | m
 设:

a = g c d ( n , m )
b = g c d ( m , n   m o d   m )

 易知:
a | n , a | m

 由储备知识3得:
a | b n + c m

 由储备知识4得:
n   m o d   m = n q m ( q Z )

 所以:
a | n   m o d   m

 由 a | n   m o d   m a | m
 得:
g c d ( m , n   m o d   m ) a

 即:
b a

 易知:
b | m , b | n   m o d   m

 即:
b | m , b | n q m

 由储备知识3易得:
b | m , b | n

 因此:
g c d ( n , m ) b

 即:
a b

 所以:
a = b

 即:
g c d ( n , m ) = g c d ( m , n   m o d   m )

以上就是gcd核心内容的证明。
上面其实是一个递归的过程,如何判断其何时终止呢?
我们知道除数不能为0,且0和任何的 a Z , a 0 都有 g c d ( a , 0 ) = a ,因此当 m = 0 n 0 时, g c d ( n , m ) = n ,这就是终止条件。
(据说 g c d ( 0 , 0 ) = 无穷大)

编程实现

gcd是很容易编程实现的,明摆着就是一个裸的递归过程,因此用函数递归是最容易实现的。
递归实现:
C++版:

long long gcd(long long n, long long m)
{
    if (m == 0) return n;
    else return gcd(m, n % m);
}

C++简洁版:

long long gcd(long long n, long long m)
{
    return m ? gcd(m, n % m) : n;
}

Pascal版:

扫描二维码关注公众号,回复: 3477960 查看本文章
function gcd(n, m:int64):int64;
begin
    if m = 0 then exit(n)
    else exit(gcd(m, n mod m));
end;

当然也有迭代实现(也就是循环实现)的,常数上可能稍微快一些。
迭代实现:
C++版:

long long gcd(long long n, long long m)
{
    while (m)
    {
        n %= m;
        swap(n, m);
    }
    return n;
}

Pascal版:

function gcd(n, m:int64):int64;
var t:int64;
begin
    while m <> 0 do
    begin
        t:= m;
        m:= n mod m;
        n:= t;
    end;
    exit(n);
end;

终于把用了这么久的gcd证明出来了。

猜你喜欢

转载自blog.csdn.net/er111er/article/details/79251895