数论

整除

对任意 定义 ,它由 的所有倍数构成。对于 ,如果 则称 整除 记为 ,否则记为 。当 时,我们称 因数因子

最小公倍数、最大公因数、互素

以下选定 ,并考虑一族整数

  • 记这族整数的最小公倍数least common multiple

  • 记这族整数的最大公因数greatest common divisor

  • ,则称 互素,这也相当于说 没有 以外的公因子。

整数的带余除法

对于任意整数 ,若 ,则存在唯一的 使得

证明 不妨假定 。考虑集合

这是 的非空子集,故有极小元,记为 ;相应地 。必然有 ,否则 将给出 使得 ,与 的极小性质矛盾。这就说明 的存在性。

至于唯一性,设 ,其中 。因为 既被 整除,又有 ,易证唯一的可能是 ,从而由 推得

根据上述命题中的唯一性,带余除法中的余数 当且仅当

的非空子集,满足以下性质

此时存在唯一的 使得

上述两个性质是说 中任意两整数相加仍然在 中, 中任意整数的倍数仍然在 中。

证明 先讨论 的存在性。不妨设 ,否则唯一的取法是 。注意到 。取 中的最小正整数。包含关系 自明。至于 ,设 ,用带余除法表为 ,其中 。不难验证 属于 ,于是 必为 ,否则将给出 中比 更小的正整数,矛盾。

至于 的唯一性,若正整数 满足 ,则它们相互整除,故唯一的可能是

对给定的 ,定义 的子集

按照惯例,极端情形 (即“空和”)按 来解释。

Bézout's identity(裴蜀恒等式 )

为整数,则

作为推论, 互素的充要条件是存在 使得

证明 不妨设 不全为 ,否则等式两边按定义同等于 。据上述引理取 ,使得 。不难验证对于任意正整数 ,我们有

这就足以表明

基于上述结果, 蕴含 可以表为 的形式;反之,若存在 使得 ,则 当然互素。

Euclid's lemma

使得 ,则

证明 由于 ,裴蜀定理蕴含存在 使得 。于是 ,而 ,所以有

计算 gcd(a, b)

求正整数 的最大公因数。

不妨设 。设 用带余除法表作 ,其中 。若 的公因数,则 整除 ;反之,若 的公因数则 整除 。即 有同一群公因数,自然有

这引出如下递归算法:

一言以蔽之,从 开始反复作带余除法,直到余数为零。

此算法称为辗转相除法,也称欧几里得算法Euclid's algorithm

例子:计算

用辗转相除法计算 的过程可以用如下序列表示

从第三项开始,每一项都是前两项相除的余数;这样反复做带余除法,直到余数为

前一次的除数是下一次的被除数,而余数(可视为被除数的“残留”)是一下次的除数;被除数与除数前后角色翻转,此即“辗转”之义。

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

辗转相除法的时间复杂度

。辗转相除计算 最多可能做多少次除法?

用辗转相除法计算 的最大公因数,假设一共做了 次除法运算,那么我们得到两个序列

  • 余数序列:
  • 商序列:

对每个 ,有

是正整数, 除以 的余数。那么

证明 ,那么根据余数的定义有 。若 ,那么

是整数,。用辗转相除法计算 ,做除法的次数不超过

证明:假设一共做了 次除法,写出余数序列

我们有

根据上一页的命题,我们有

分别看 ,有

是奇数,我们有

也就是有 ,所以

为偶数,此时 ,必有 ,我们有

也就是有 ,所以

计算 lcm(a, b)

求正整数 的最小公倍数。

对任意正整数

证明,则根据最大公因数的定义,存在整数 使得

,代入 。于是有 ,可见 的公倍数。

的任意一个公倍数,即 。以 代入 ,所以存在整数 使得 。以 代入 ,得 。两边约去 ,得 。由于 ,根据欧几里得引理,必有 。所以存在整数 ,使 ,代入 ,得 。因为 是整数,所以

因为 的任意公倍数都能被 整除,且 的公倍数,所以 就是 最小公倍数。

丢番图方程

是整数,求方程 的整数解。

根据 Bézout's identity,,所以方程有解当且仅当

是整数, 不都是 。设整数 满足 ,那么方程 的全部整数解为

其中 是任意整数。

证明:先证充分性。
。将 代入 ,得

所以 是方程的解。

再证必要性。
是方程的任意一组整数解,即 ,同时我们有 ,两式相减,得 ,即

,此时必然有 ,代入上式并除以 ,得

于是可见 整除 。由于 ,根据欧几里得引理,我们有

也就是说,存在整数 使得 ,即

,即 ,此时必有 ,则 的值唯一,是 ,而 可取任一整数。此时 ,所以 确实可以取到每个整数。

,将 代入 并除以 ,得 ,即

丢番图方程

是整数,求方程 的整数解。

扩展 gcd 算法

我们用辗转相除法计算 ,除了可以得到 ,还能得到两个整数 使得 。这就是所谓扩展 gcd 算法

具体的计算方法有两种:一是正推,一是倒推。

正推的扩展 gcd 算法

用辗转相除法计算 ,写出余数序列

我们可以按 的顺序,把每个 写成

的形式,其中 是整数。

最后 就使得 .

我们取

代入

改写成

我们可以取

我们以计算 为例,演示正推的扩展 gcd 算法。

pair<int,int> extgcd(int a, int b) {
    int u = 1, v = 0;
    while (b != 0) {
        int q = a % b;
        a -= q * b;
        u -= q * v;
        swap(a, b);
        swap(u, v);
    }
    return {a, u};
}

extgcd(a, b) 返回的两个整数依次是

  • 一个整数 使得 整除

倒推的扩展 gcd 算法

用辗转相除法计算 ,写出余数序列

我们可以按 的顺序,把 写成

的形式,其中 是整数。

最后, 就使得

就是 ,我们取

代入 ,得

改写成

将此式与 对比,可见我们可以取

我们以计算 为例,演示倒推的扩展 gcd 算法。

int extgcd(int a, int b, int& x, int& y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    int q = a % b;
    int g = extgcd(b, a - q * b, y, x);
    y -= x * q;
    return g;
}

正推

倒推

正推和倒推给出的 是一样的,这并非巧合。

C++ 里的 % 运算符和 / 运算符。

是整数,

  • 如果 整除 ,那么 。如果 不整除 ,此时必有 ,那么 的符号与 相同,
  • a == (a / b) * b + (a % b) 总是成立。

扩展 gcd 算法给出的 x, y 的大小

是整数,。设 ,那么 extgcd(a, b, x, y) 给出的 满足

证明:用归纳法。

时,extgcd(a, b, x, y) 给出 ,命题成立。
时,设 a / b。根据归纳假设,递归调用 extgcd(b, a % b, y, x) 给出的 满足 。根据 ,有

注意到 符号相同,所以 。于是有

解丢番图方程

此方程有解当且仅当

具体的,如果 ,也就是 ,那么当且仅当 时有解,此时任意整数 都是解。

如果 不全是 ,那么

  1. 用扩展 gcd 算法算出 和整数 使得
  2. 如果 ,那么 就是 的一个解,否则方程无解。

在计算时需要注意

  • 较大时, 可能溢出。

我们可以这样做

  • 分别是 除以 的商和余数。那么 的一个解。

同余式

。称 是 mod 同余的,如果 ;此关系也写作

线性同余方程

是整数,。求方程 的整数解。

整数 使得 ,也就是说存在整数 使得 。于是可见同余方程 和丢番图方程 同解。我们立即得到

  • 存在整数 使得 当且仅当
  • 设整数 是方程 的一个解,那么此方程的全部整数解为 ,其中 是任意整数。也就是说 等价。

线性同余方程组

是整数,
求方程组 的整数解。

整数 满足 ,也就是说 使得

  • 存在整数 满足

所以这样的 和满足 的整数对 一一对应。可见 就是丢番图方程 的解 。设 是一个解,那么全部解为

其中 是任意整数。将上式代入 ,得

注意到 就是 。于是可见

  • 方程组 等价于

素数

。如果 除了 之外没有别的因数,则称 素元。正的素元称为素数

算术基本定理

任何非零整数 都有素因子分解

其中 (当 时右式规定为 ), 是相异素数,,而且此分解不论顺序是唯一的。

证明 关于分解的存在性,处理 的情形即可。我们寻求形如 的分解。如果 既非 又非素数,则分解为 ,其中 。继续对 递归地操作,最终可表 为若干个素数的乘积,容许重复。

唯一性仍可简化到 的情形。设 ,其中 是相异素数, 也是相异素数,而 。注意到 当且仅当 ,此时两边都是 。故以下不妨设

由于 ,反复应用欧几里得引理可知存在 使得 ;这进一步蕴含 。重排下标后不妨假设 ,必要时等号两边互换,不妨假设 。于是

再次应用欧几里得引理可见 不整除左式,故 。按此递归地论证,即得分解的唯一性。

算术基本定理的推论

  • 对于任何素数 和非零整数 ,我们有 当且仅当 的素因子分解中出现,相应的指数 由以下性质唯一确定:,数论中的标准记法如下

    • 为素数,我们以符号 表达
  • 考虑正整数 ,其中 是相异素数而 ,则

    • 对于任意多个正整数的 也有类似结果。

有无穷多个素数

素数列 是数论关切的基本对象;这方面最古老也是最基础的结果是

存在无穷多个素数。

证明 对任意一列素数 ,考虑

,而且它不被 中任一个素数整除。因此 的素因子分解中必有不同于 的素数。

这样对齐会导致 \implies 左边的空格较小,不是正确的对齐方式。

首先我们写出 $$ \begin{align} \gcd(a, b) &= x_i r_i + y_i r_{i+1} \label{eq} \tag{1} \\ \gcd(a, b) &= x_{i-1} r_{i-1} + y_{i-1} r_i \label{eq2} \tag{2} \end{align} $$