数论 for OI

18年讲了一遍oi数论,上学期听了两遍初等数论,这学期又听了一遍,马上又要讲,于是写了一份讲义。写的时候感觉要把一个脑子里知道的结构描述出来真的很难,有时候句子都写不通顺了。

1 整数集上的整除关系

1.1 定义

对于\(a, b \in \mathbb{Z}\),如果存在\(c \in \mathbb{Z}\),使\(a=bc\),则说\(b\)整除\(a\),记作\(b|a\),并称\(a\)\(b\)的一个倍数,\(b\)\(a\)的一个约数. 下文的大部分讨论是在非负整数集\(\mathbb{N}\)上进行的.

1.2 性质

在这里仅指出一些比较常用的性质:

  • 整除具有传递性,如果\(a|b, b|c\),则有\(a|c\)
  • 任何整数都能整除\(0\)
  • 如果\(a|b\)\(a|c\),那么\(a\)也能整除\(b\)\(c\)的任何整倍数组合,即\(\forall x, y \in \mathbb{Z}, a|(bx+cy)\)

1.3 约数

如果\(d\)\(a\)的一个约数,那么\(\frac{a}{d}\)也是\(a\)的一个约数. 当\(d<\sqrt{a}\)时,\(\frac{a}{d}>\sqrt{a}\),反之亦然. 因此我们看到,一个正整数\(a\)的约数中,小于\(\sqrt{a}\)的部分和大于\(\sqrt{a}\)的部分是成对出现的,每一对\(d_1, d_2\)都满足\(d_1d_2=a\)

还有一个特殊情况:如果\(a\)是完全平方数,\(\sqrt{a}\)本身也是\(a\)的一个约数,它与自己成对出现.

到这里容易观察到约数的一些性质:\(a\)的约数数量不超过\(2\sqrt{a}\)——当然这是一个很松的上界. 非完全平方数的约数可以被完美地划分为一一对应的两部分,因此有偶数个约数. 而完全平方数会多出一个\(\sqrt{a}\)作为约数,因此有奇数个约数.

1.4 素数

如果一个正整数仅有自身和\(1\)两个约数,则称为素数. 在OI中,我们首先关心的是怎样判断一个数是否是素数,以及找出某个范围内的所有素数.

如果\(n\)是合数,那么它一定有至少一个不超过\(\sqrt{n}\)且不是1的约数. 因此素性检测最朴素的做法是在\([2, \sqrt{n}]\)中枚举并试除即可,复杂度为\(O(\sqrt{n})\). 在\(n\)更大时,OI中常用的算法是Miller-Rabin素性测试,如果有兴趣可以自行了解. 素性测试是一个经典的算法问题,学术界在这一问题上也有许多已有的成果,不过大多由于过于复杂,OI中并不涉及.

给定一个上界\(n\),筛法可以用来求出不超过\(n\)的所有素数. 为范围内的每个整数置一个标记,初始为false,枚举\([2, \sqrt{n}]\)中的所有整数\(d\),再将\(d\)的所有不超过\(n\)的倍数的标记置为true. 这样一来,所有合数都会被筛掉. 略去取整,它的时间代价是:

\[\sum_{d=2}^{\sqrt{n}} \frac{n}{d}=n\sum_{d=2}^{\sqrt{n}}\frac{1}{d} \]

由于调和级数在\(n \rightarrow \infin\)时有近似\(H_n \sim \ln n\),这一筛法的时间复杂度为\(O(n \log n)\)

注意到在枚举\(d\)时,作为合数的\(d\)是没有意义的,因为被它筛掉的数一定也会被\(d\)的某个质因子筛掉,因此可以仅在\(d\)是质数时对它的倍数进行枚举,这被称为埃氏筛法,时间复杂度改进到\(O(n \log \log n)\)

这一筛法依然是有浪费的,因为一个整数可能会被它的多个质因子重复筛掉. 欧拉筛让每个合数在它的最小质因子处被筛掉,从而达到了\(O(n)\)的时间复杂度. 它的算法过程如下:

  • 将[2, n]的所有标记置false,维护一个质数列表,初始为空
  • \(2\)\(n\)枚举\(i\)
    • 如果\(i\)的标记依然是false,则将\(i\)加入质数列表的末尾
    • 从前向后枚举质数列表中的质数\(p_j\)
      • 如果\(i \cdot p_j\)过大(超过\(n\))则停止
      • \(i \cdot p_j\)标记为true
      • 如果\(p_j|i\),则停止. 这意味着此时\(p_j\)\(i\)的最小质因数,而在这之前(包括这一个),\(p_j\)都是\(i \cdot p_j\)的最小质因数.

由于每个合数仅会在\(p_j\)取它的最小质因子时被作为\(i \cdot p_j\)枚举到,内层枚举的次数也不超过\(n\),时间复杂度是\(O(n)\).

std::vector<int> primes;
for(int i = 2; i <= n; ++i)
{
    if(!vis[i]) primes.push_back(i);
    for(size_t j = 0; j < primes.size(); ++j)
    {
        int cur = i * primes[j];
        if(cur > n) break;
        vis[cur] = true;
        if(i % primes[j] == 0) break;
    }
}

1.5 带余除法

对于\(a, b \in \mathbb{Z}, b>0\),总可以找到恰好一组\(q, r \in \mathbb{Z}\),使得

\[a=qb+r, 0 \leq r < b \]

\(q\)被称为\(a\)除以\(b\)的商,\(r\)是余数.

\(a\)除以\(b\)求余数的运算称作取模,记为\(r=a \bmod b\).

\(q\)是对\(\frac{a}{b}\)向下取整的结果,即\(q=\lfloor \frac{a}{b} \rfloor\),因此取模运算满足\(a \bmod b=a-\lfloor \frac{a}{b} \rfloor b\)

1.6 算术基本定理

我们不加证明地给出算术基本定理:任何正整数都可以唯一地表示成一组非降素数的乘积. 例如\(60=2 \times 2 \times 3 \times 5\). 一般我们将同一个质因子合并,写成\(n=\prod_i p_i^{q_i}\)的形式.

这个定理可以帮助我们了解许多\(\mathbb{Z}\)的性质. 如果我们将那些在乘积中没有出现的素数也列出来,并把它的次数记为\(0\),则任何一个正整数都可以写成下面的形式:

\[n=2^{q_1}3^{q_2}5^{q_3}7^{q_4}\dots \]

这是一个无穷乘积,但其中仅有有限多个\(q_i\)是非零的. 这样一来,任何一个\(n \in \mathbb{Z}\)都对应着\(q_1, q_2, \dots\)这样一个无穷序列. 两个整数相乘对应着两个序列对应位置的相加.

在处理整除相关的问题时,这种看法有时会更加方便. 例如,如果\(a|b\),则\(a\)的指数序列上对应位置总是小于等于\(b\). 这样也容易发现,如果枚举\(n\)的所有约数,就等价于在每个\(q_i\)处让约数的指数取遍\(0\)\(q_i\). 因此\(n\)的约数数量\(\sigma_0(n)=\prod_i(q_i+1)\)

在进行质因子分解时,考虑到\(n\)至多有一个大于\(\sqrt{n}\)的质因子,朴素算法容易降低到\(O(\sqrt{n})\)

std::vector<std::pair<int, int> > factors;
for(int i = 2; i * i <= n; ++i)
{
    if(n % i == 0)
    {
        int cnt = 0;
        while(n % i == 0)
        {
            n /= i;
            ++cnt;
        }
        factors.push_back(std::make_pair(i, cnt));
    }
}
if(n > 1) factors.push_back(std::make_pair(n, 1));

1.7 最大公约数,最小公倍数

\(a, b\)的公共正因子中最大的那个称为\(a\)\(b\)的最大公约数,记作\((a, b)\),OI中一般记作\(\gcd(a, b)\)

如果观察质因子分解结果,容易发现\(\gcd(a, b)\)的每个指数都是\(a, b\)在对应位置上指数的最小值. 因此\(a, b\)的公共正因子集合正是\(\gcd(a, b)\)的因子集合.

同理,最小公倍数\(\mathrm{lcm}(a, b)\)是质因子分解中对应位置指数取最大值的结果. 观察到

\[\min(q_i, q_i')+\max(q_i, q_i')=q_i+q_i' \]

这意味着

\[\gcd(a, b) \cdot \mathrm{lcm}(a, b) = ab \]

\(a, b\)的公共正因子集合记为\(CD(a, b)\),则\(\gcd(a, b)\)是其中的最大元.

容易自行验证,将\(a\)加上若干倍的\(b\),则\(a, b\)的公共正因子集合不会改变,即

\[CD(a+kb, b)=CD(a, b), k \in \mathbb{Z} \]

反之,对\(b\)加上若干倍的\(a\)也是一样.

考虑到\(a \bmod b=a-\lfloor \frac{a}{b} \rfloor b\),我们得到\(\gcd(a, b)=\gcd(a \bmod b, b)\). 利用这一性质,求\(\gcd(a, b)\)时,只需不断地用较大的模较小的,过程中公共正因子集合不变,直至其中一个为零,另一个非零整数即为答案. 这一算法就是欧几里得算法,也被称为辗转相除法.

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

1.8 互质

如果两个整数的最大公因数是\(1\),则说它们互质. 考虑质因数分解,容易发现互质等价于质因子集合没有交集.

2 同余

2.1 定义

如果\(m|(a-b)\),则称\(a\)\(b\)\(m\)同余,记作\(a \equiv b \pmod m\)

因此可以发现,如果\(n|m\),那么\(a \equiv b \pmod m \Rightarrow a \equiv b \pmod n\)

在模数为\(m\)时,依据同余关系可以把整数集分为\(m\)个模\(m\)剩余类,分别是模\(m\)得到\(0, 1, \dots, m-1\)的整数组成的. 从每个剩余类中取一个元素,组成一个集合,就称为一个模\(m\)完全剩余系. 比较常用的模\(m\)完全剩余系是\(0, 1, \dots, m-1\)

在模\(m\)意义下,容易验证加法、减法、乘法的结构是保持的,因此可以直接把这些运算搬到一个完全剩余系上. 但是除法却不太容易进行:例如模\(6\)时,\(5 \times 2 \equiv 2 \times 2 \equiv 4 \pmod 6\),那么在模意义下用\(4\)除以\(2\)应该得到\(2\)还是\(5\)呢?

2.2 除法

在模\(m\)意义下做除法,就等价于给定\(a, c\),解同余方程\(ax \equiv c \pmod m\). 如果除法能够进行,就意味着这个同余方程有唯一解,而它又等价于下列不定方程:

\[ax + my = c \]

这是由同余的定义得到的,下面我们对这种不定方程进行更深入的探讨.

2.3 Bezout定理

形如\(ax+by=c\)的不定方程有整数解的充要条件是\(\gcd(a, b)|c\)

证明:

考虑\(ax+by, x,y \in \mathbb{Z}\)可能取到的所有值,设其为\(I_{a,b}\),即

\[I_{a,b}=\lbrace ax+by | x, y \in \mathbb{Z} \rbrace \]

该不定方程有整数解当且仅当\(c \in I_{a, b}\),因此我们希望弄清楚\(I_{a,b}\)的结构. 容易验证\(I_{a, b}\)对加减法、取模都是封闭的,下面我们取出\(I_{a,b}\)中的最小正元素,设其为\(d\).

由于存在一组\(x, y \in \mathbb{Z}\)使\(d=ax+by\),可以发现\(\gcd(a, b) | d \Rightarrow \gcd(a, b) \leq d\).

由于\(a, b\)都在\(I_{a,b}\)中,考虑到取模的封闭性,\(a \bmod d\)\(b \bmod d\)都在\(I_{a,b}\)中,并位于\([0, d)\)里. 但是考虑到\(d\)是最小正元素,它们不能取\((0, d)\)中的值,因此\(a \bmod d=b \bmod d=0\),即\(d|a, d|b\). 这样一来,\(d\)\(a, b\)的公约数,于是有\(d \leq \gcd(a, b)\). 综合上一段的结论,得到\(d=\gcd(a, b)\)

类似地,利用取模的封闭性,可以发现\(I_{a,b}\)中的所有元素都是\(d\)的倍数. 到这里,\(I_{a,b}\)的结构很清晰了——它恰好包含\(\mathrm{gcd}(a, b)\)的所有倍数:

\[I_{a,b}=\lbrace 0, \pm \gcd(a, b), \pm 2\gcd(a, b), \dots \rbrace \]

于是证明了Bezout定理.

回到上一节的同余方程,Bezout定理意味着\(ax \equiv c \pmod m\)\(\gcd(a, m) | c\)时一定有解,而在\(\gcd(a, m) \nmid c\)时一定无解.

2.4 扩展欧几里得算法

证明了解的存在性后,需要一个算法在解存在时找出\(ax+by=c\)的解.

在欧几里得算法的最后一步,即\(a'=\gcd(a, b), b'=0\)时,解\(a'x+b'y=c\)是十分容易的:只需取\(x=\frac{c}{\gcd(a, b)}, y=0\). 下面在回溯过程中逐步倒推,得到最初的\(ax+by=c\)的解:

\(a, b\)得到\(b, a \bmod b\)后,下一层递归并回溯得到了\(bx'+(a \bmod b)y'=c\)的一组解\(x', y'\).

考虑到\(a \bmod b = a- \lfloor \frac{a}{b} \rfloor b\),代入得到\(bx'+(a- \lfloor \frac{a}{b} \rfloor b)y'=c\),将\(a, b\)的系数整理得到:

\[ay'+b(x'-\lfloor \frac{a}{b} \rfloor y')=c \]

因此只需取\(x=y', y=x'-\lfloor \frac{a}{b} \rfloor y'\)即可

void exgcd(int a, int b, int c, int &x, int &y)
{
    if(b == 0)
    {
        // assert: c % a == 0
        x = c / a;
        y = 0;
        return;
    }
    int k = a / b;
    exgcd(b, a - k * b, c, y, x);
    y -= k * x;
}

2.5 \(f(x)=ax \bmod m\)的性质

想象一个钟面上顺时针刻着\(0, 1, \dots, m-1\),从\(0\)出发,每一步向前前进\(a\)格,即从当前位置\(c\)前进到\((c+a) \bmod m\),那么哪些位置会被走到?

这其实对应着\(f(x) = ax \bmod m\),由于\(x\)取模\(m\)同余的值时函数值显然相同,我们只考虑\(0 \leq x < m\).

在下面的讨论中,设\(d=\gcd(a, m)\)

根据2.3中的结论,我们知道\(f(x)\)会且只会取到\([0, m)\)中被\(d\)整除的那些值,共\(\frac{m}{d}\)个.

同时,考虑两个相差\(\frac{m}{d}\)的位置的函数值:

\[f(x+\frac{m}{d})=a(x+\frac{m}{d}) \bmod m=(ax + \frac{a}{d}m) \bmod m=ax \bmod m=f(x) \]

发现\(f(x)\)\(\frac{m}{d}\)的周期. 同时考虑到值域中的\(\frac{m}{d}\)个值都要被取到,它们在一个周期中都被取到了恰好一次.

于是\(f(x)\)的结构就很清晰了:它以\(\frac{m}{d}\)为周期,每个周期中将\(d\)\(\frac{m}{d}\)个倍数取遍一次. 在\(x\)取遍\(0, 1, \dots, m-1\)时,它重复了\(d\)个周期.

2.6 乘法逆元

根据上一节的讨论,我们考虑一个特殊情形:在\(a\)\(m\)互质时,\(d=1\).

这意味着当\(x\)取遍一次\(\mathbb{Z}_m\)时,\(ax\)也取遍一次\(\mathbb{Z}_m\). 这正好满足了做除法的要求:\(x \rightarrow ax\)是一个\(\mathbb{Z}_m\)\(\mathbb{Z}_m\)的双射,因此任给一个\(c \in \mathbb{Z}_m\)\(ax \equiv c \pmod m\)总有恰好一个解.

这也带来了一些其他的性质:由于\(f\)是单射,有\(ax \equiv ay \pmod m \Rightarrow x \equiv y \pmod m\),这意味着可以从同余等式的两边消去同一个与模数互质的因子.

注意到\(ax \equiv 1 \pmod m\)也仅在\(\gcd(a, m)=1\)时有解. 这个方程的解被称为\(a\)的乘法逆元,记作\(a^{-1}\),因为它的表现就像实数乘法中的\(\frac{1}{a}\)一样.

模意义下的乘法保持了交换律和结合律——这允许我们十分方便地使用乘法逆元:要解\(ax \equiv c \pmod m\),只需两边左乘\(a^{-1}\)(实际上由于交换律,并不需要说明是左乘),得到

\[a^{-1}ax \equiv a^{-1}c \pmod m \]

再利用结合律,并考虑到\(a^{-1}a \equiv 1 \pmod m\)

\[x \equiv a^{-1}c \pmod m \]

类似地,将\(ax \equiv ay \pmod m\)两边乘\(a^{-1}\),便可直接得到\(x \equiv y \pmod m\)

待续:乘法的结构(原根,欧拉定理,离散对数),\(\mathbb{Z}_n\)间笛卡尔积的结构(中国剩余定理),Dirichlet卷积、Mobius反演、杜教筛

posted @ 2020-07-19 23:27  lkmcfj  阅读(268)  评论(0编辑  收藏  举报