数论算法导论


前言

数论是算法里面及其重要的组成部分,在竞赛中使用数论,通常能写出O(1)高效率级别的算法。数论包括基本概念、欧几里得算法、模运算、倍数与模、中国余数定理、幂与模、RSA算法、素数与素数测试、因数分解等核心内容。


一、数论基本概念

1.1 整除性与约数

定义:符号“d | a”(读作d整除a)的含义是,存在某个整数k,有a=kd存在。特别的任何整数均可整除0。

定理:如果a>0,且d|a,那么|d| <= |a|。

定义:如果d|a,那么a就是d的倍数,如果d不能整除a,写作 a ∤ b a \nmid b ab

定义:如果d|a且d>=0,则称d为a的约数。注意约数是0或正整数,如果d|a那么-d|a就是说,a的一个约数的负数仍可以整除a。

因此,不失一般性,规定约数为非负整数。非零整数a的约数应该至少为1,且不会大于|a|。例如,24的约数是1,2,3,4,6,8,12和24。

任何正整数a均可被平凡约数1和其自身a所整除。整数a的非平凡约数称为a的因子。例如20的因子有2,4,5,10。

1.1 素数和合数

定义:如果一个整数a>1,且只能被平凡约数整除,则这个数是素数,如果整数a>1不是素数,那么他就是合数。称整数 1 为基本单位,它既不是素数也不是合数。同样0和其他负整数既不是素数也不是合数。

1.2 除法定理、余数和等模

给定一个整数n,我们可以将整数集划分为n的倍数和非n的倍数两个部分。通过计算非n倍数除以n的余数可以对非n的倍数的部分进行有效分类。

除法定理:对于任何整数a和任何正整数n,存在唯一整数q和r,满足0<=r<n且a=qn+r

q = ⌊ a n ⌋ q = \left \lfloor \frac{a}{n} \right \rfloor q=na为除法的,值r = a mod n为除法的余数。n|a当且仅当余数为0;

我们可将除数和余数将整数集分为几个等价类。包含整数a的模n的等价类为

[ a ] n = { a + k n ∣ k ∈ Z } [a]_{n} = \{ a+kn | k \in Z \} [a]n={a+knkZ}

例如 [ 3 ] 7 = { . . . , − 11 , − 4 , 3 , 10 , 17 , . . . } [3]_{7} = \{ ...,-11,-4,3,10,17,... \} [3]7={...,11,4,3,10,17,...},这个集合也可以表示为 [ − 4 ] 7 [-4]_{7} [4]7 [ 10 ] 7 [10]_{7} [10]7。因此 a ∈ [ b ] n a \in [b]_{n} a[b]n,则 [ a ] n = [ b ] n [a]_{n} = [b]_{n} [a]n=[b]n a ∈ [ b ] n a \in [b]_{n} a[b]n a ≡ b ( m o d n ) a \equiv b(mod n) ab(modn)等价。所有这类等价的集合为

Z n = { [ a ] n ∣ 0 ⩽ a ⩽ n − 1 } Z_{n} = \{ [a]_{n}|0 \leqslant a \leqslant n-1 \} Zn={[a]n0an1}

我们用等价类的最小非负元素代表这个等价类。

我们可以这么理解,关于7的等价类有7n+1,7n+2,…,7n+6,这些集合共同组成了整数集,并把整数集分成了6个等价类,依次用123456代表,是最小非负元素。

1.3 公约数与最大公约数

定义:如果d是a的约数,d也是b的约数,则d是a和b的公约数。1是任意两个整数的公约数。

定理:若d|a,d|b则有d|(a+b)和d|(a-b),更一般的,对于任意整数x和y有d|(xa+yb)

推论:如果a|b且b|a那么 a = ± b a = \pm b a=±b

两个不同时为0的整数a和b的公约数中最大的叫做最大公约数,记作gcd(a,b)。特别的,定义gcd(0,0) = 0,0的最大约数不存在。

给出以下定理:

  1. gcd(a,b) = gcd(b,a)
  2. gcd(a,b) = gcd(-a,b)
  3. gcd(a,b) = gcd(|a|,|b|)
  4. gcd(a,0) = |a|
  5. gcd(a,ka) = |a| , k ∈ Z k \in Z kZ

最大公约数线性组合定理:如果任意整数a和b都不为0,那么gcd(a,b)是a和b的线性组合中的最小的正元素

推论:对于任意整数a和b,如果d|a且d|b,则d|gcd(a,b)。

推论:对于a和b和任意的非负整数n,有gcd(a,b) = n gcd(a,b)

推论:对于任意的正整数n、a和b,如果n | ab 且 gcd(a,n) = 1,则n | b。(算法导论留作练习,这里给出我的证明)

证明:

∵ g c d ( a , b ) = 1 ∴ ∃ x , y ∈ Z , a x + n y = 1 ∵ n ∣ a b ∴ ∃ k ∈ Z , a b = k n ∴ b a x + b n y = b ∴ k n x + b n y = b ∴ n ( k x + b y ) = b ∴ n ∣ b \because gcd(a,b) = 1 \\ \therefore \exists x,y \in Z,ax+ny = 1 \\ \because n \mid ab \\ \therefore \exists k \in Z,ab = kn \\ \therefore bax+bny = b \\ \therefore knx+bny = b \\ \therefore n(kx+by) = b \\ \therefore n \mid b gcd(a,b)=1x,yZ,ax+ny=1nabkZ,ab=knbax+bny=bknx+bny=bn(kx+by)=bnb

1.4 互质数

定义:如果两个整数a和b只有公约数1,且gcd(a,b) = 1 ,则称a和b为互质数

定理:对于任意整数a、b和p,如果gcd(a,p)=1且gcd(b,p)=1,则gcd(ab,p)=1。

定义:给出一组数,如果任意两个元素互质,则称这组数两两互质

1.5 唯一因子分解定理

定理:对于所有素数p和所有整数a和b,如果p|ab,则p|a或p|b或两者都成立。

唯一素因子分解定理:合数a仅能以一种方式写成如下乘积的形式:

a = p 1 e 1 × p 2 e 2 × p 3 e 3 × p 4 e 4 × . . . × p n e n a=p_{1}^{e_{1}} \times p_{2}^{e_{2}} \times p_{3}^{e_{3}} \times p_{4}^{e_{4}} \times ... \times p_{n}^{e_{n}} a=p1e1×p2e2×p3e3×p4e4×...×pnen

其中 p i p_{i} pi为素数, p 1 < p 2 < . . . < p n p_{1} < p_{2} < ... < p_{n} p1<p2<...<pn,且 e i e_{i} ei为正整数。

证明:

存在性:一个合数可以拆成两个非1约数相乘,这两个约数要么都是合数,要么都是素数,要么一个是合数一个是素数。如果都是素数则满足要求,如果约数里面有合数,那么将这个合数继续往下拆解,且继续向下拆解的合数一定是小于原合数,如此往复一定能拆到最小合数4,4能拆成素数2和2相乘,因此一个合数一定可以拆成n个素数相乘的形式。

唯一性:反证法,假设存在另外一种乘积形式

a = P 1 c 1 × P 2 c 2 × P 3 c 3 × P 4 c 4 × . . . × P r c r a=P_{1}^{c_{1}} \times P_{2}^{c_{2}} \times P_{3}^{c_{3}} \times P_{4}^{c_{4}} \times ... \times P_{r}^{c_{r}} a=P1c1×P2c2×P3c3×P4c4×...×Prcr

两种乘积形式不同,联立有

1 = P 1 c 1 × P 2 c 2 × P 3 c 3 × P 4 c 4 × . . . × P r c r p 1 e 1 × p 2 e 2 × p 3 e 3 × p 4 e 4 × . . . × p n e n 1= \frac { P_{1}^{c_{1}} \times P_{2}^{c_{2}} \times P_{3}^{c_{3}} \times P_{4}^{c_{4}} \times ... \times P_{r}^{c_{r}} }{ p_{1}^{e_{1}} \times p_{2}^{e_{2}} \times p_{3}^{e_{3}} \times p_{4}^{e_{4}} \times ... \times p_{n}^{e_{n}} } 1=p1e1×p2e2×p3e3×p4e4×...×pnenP1c1×P2c2×P3c3×P4c4×...×Prcr

又因为,素数和素数两两互质,所以右侧分式不可能等于1,因此两个乘积形式应该相同。

结合存在性和唯一性,即可推出唯一素因子分解定理。


二、最大公约数

2.1 欧几里得算法

GCD递归定理:对于非负的整数a和b,有gcd(a,b) = gcd(b,a mod b)

证明参考《算法导论》。

由GCD递归定理我们可以写出欧几里得算法:

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

注意,该算法不是多项式时间复杂度。

2.2 欧几里得算法运行时间分析

引理: 如果 a > b ≥ 1 a>b \geq 1 a>b1并且euclid(a,b)执行了 k   g e q 1 k \ geq 1 k geq1次的递归调用,则 a ≥ F k + 2 , b ≥ F k + 1 a \geq F_{k+2} ,b \geq F_{k+1} aFk+2,bFk+1,其中 F n F_{n} Fn为第n个斐波那契数。

Lame定理:对任意整数 k ≥ 1 k \geq 1 k1,如果 a > b ≥ 1 a>b \geq 1 a>b1,且 b < F k + 1 b < F_{k+1} b<Fk+1,则euclid(a,b)的递归调用次数小于k次。

因此,根据黄金分割比逼近法,递归调用次数的上界应该是O(lgn),如果euclid作用于两个 β \beta β位的数,他将执行 O ( β ) O(\beta) O(β)次的算术运算和 O ( β 3 ) O(\beta^{3}) O(β3)次的位操作。

2.3 欧几里得算法的扩展形式

因为d=gcd(a,b)=ax+by,我们有时候想知道x和y比d更有用一些。

struct Res
{
    int d;
    int x;
    int y;
};

Res extendedEuclid(int a, int b)
{
    if (b == 0)
    {
        return {a, 1, 0};
    }
    else
    {
        Res r = extendedEuclid(b, a % b);
        return {r.d, r.y, r.x - a / b * r.y};
    }
}

证明:
当b==0时易得结果,当b不等于0时,我们计算得到了 d ′ = b x ′ + ( a   m o d   b ) y ′ d' = bx'+(a \ mod \ b)y' d=bx+(a mod b)y,由余数的定义改写一下:

d ′ = b x ′ + ( a − ⌊ a b ⌋ × b ) y ′ d' = bx'+(a - \left \lfloor\frac{a}{b} \right \rfloor \times b)y' d=bx+(aba×b)y

整理得到:

d ′ = b ( x ′ − ⌊ a b ⌋ × y ′ ) + a y ′ d' = b(x' - \left \lfloor\frac{a}{b} \right \rfloor \times y') + ay' d=b(xba×y)+ay

欧几里得扩展算法的时间复杂度分析也同理于欧几里得算法。


三、模运算

3.1 有限群

定义: ( S , ⨁ ) (S,\bigoplus) (S,) 是一个集合S和定义在S上的二元运算 ⨁ \bigoplus ,该运算满足下列性质:

  1. 运算封闭性 ∀ a , b ∈ S , a ⨁ b ∈ S \forall a,b \in S,a \bigoplus b \in S a,bS,abS
  2. 存在单位元:存在一个元素 e ∈ S e \in S eS,称为该群的单位元,满足 ∀ a ∈ S , e ⨁ a = a ⨁ e = a \forall a \in S,e \bigoplus a = a \bigoplus e = a aS,ea=ae=a
  3. 满足结合律 ∀ a , b , c ∈ S , ( a ⨁ b ) ⨁ c = a ⨁ ( b ⨁ c ) \forall a,b,c \in S,(a \bigoplus b) \bigoplus c = a \bigoplus (b \bigoplus c) a,b,cS,(ab)c=a(bc)
  4. 存在逆元 ∀ a ∈ S , ∃ b ∈ S , a ⨁ b = b ⨁ a = e \forall a \in S,\exist b \in S,a \bigoplus b = b \bigoplus a = e aS,bS,ab=ba=e,称a和b互逆

如果一个群满足 ∀ a , b ∈ S , a ⨁ b = b ⨁ a \forall a,b \in S,a \bigoplus b = b \bigoplus a a,bS,ab=ba,则称这个群为交换群;如果群满足 ∣ S ∣ < ∞ |S| < \infty S<,则称群为有限群。

3.2 由模加法和模乘法所定义的群

通过对模n运用加法运算,乘法运算,可以得到两个有限交换群,其中n是正整数。这些群运算基于整数n模定义的等价类

注意:下列的数字不仅仅包括数字本身,还包括数字在n模下的等价类中的所有数字。

我们基于数的加法和乘法,定义模运算的加法和乘法。

定义:模运算等价类加法 [ a ] n + [ b ] n = [ a + b ] n [a]_{n} + [b]_{n} = [a + b]_{n} [a]n+[b]n=[a+b]n,其中 [ a ] n [a]_{n} [a]n [ b ] n [b]_{n} [b]n是两个等价类。减法同理。

定义:模运算等价类乘法 [ a ] n ⋅ [ b ] n = [ a ⋅ b ] n [a]_{n} \cdot [b]_{n} = [a \cdot b]_{n} [a]n[b]n=[ab]n,其中 [ a ] n [a]_{n} [a]n [ b ] n [b]_{n} [b]n是两个等价类。

可以说明,我们在计算等价类的时候,可以很方便的用最小非负整数代表等价类,也具有一般性。一般的,我们在计算完结果的时候,都要把结果最简化。例如: [ 3 ] 7 + [ 5 ] 7 = [ 1 ] 7 [3]_{7} + [5]_{7} = [1]_{7} [3]7+[5]7=[1]7,这里用 [ 1 ] 7 [1]_{7} [1]7代替 [ 8 ] 7 [8]_{7} [8]7

这样,我们可以定义模n的加法群 ( Z n , + n ) (Z_{n},+_{n}) (Zn,+n),他的规模为 ∣ Z n ∣ = n |Z_{n}| = n Zn=n,如下表:(时刻记住这些不是数,而是代表的等价群)

+012345
0012345
1123450
2234501
3345012
4450123
5501234

定理:群 ( Z n , + n ) (Z_{n},+_{n}) (Zn,+n)是一个有限交换群。单位元是0,逆元是-a或者n-a。

定义:模n的乘法群 ( Z n ∗ , ⋅ n ) (Z_{n}^{*},\cdot_{n}) (Zn,n),注意: Z n ∗ Z_{n}^{*} Zn Z n Z_{n} Zn中与n互质的元素的集合。

为什么必须要互质呢?因为如果不互质,那么该乘法群不满足只有唯一单位元的条件,有多个不同的单位元,不满足群的要求。但是它的子群,即与n互质元素的集合构成的群满足单一单位元,即1

定理:模n的乘法群也是一个有限的交换群。

然后我们讨论一下乘法群的逆元和规模。

设a是 Z n ∗ Z_{n}^{*} Zn里面的一个元素,我们想求他的逆元,我们可以先计算 ( d , x , y ) = e x t e n d e d E u c l i d ( a , n ) (d,x,y)=extendedEuclid(a,n) (d,x,y)=extendedEuclid(a,n),又因为a与n互质,所以d=1,因此存在ax+ny=1,因此 a x ≡ 1 ( m o d   n ) ax \equiv 1 (mod \ n) ax1(mod n),所以x就是a的逆元。且关于x和n的线性组合ax+ny最小正整数为1,因此gcd(x,n)=1,因此x也属于乘法群中的元素。

把a的逆元用 a − 1 ( m o d   n ) a^{-1}(mod \ n) a1(mod n)来表示,除法用 a b ≡ a b − 1 ( m o d   n ) \frac{a}{b} \equiv ab^{-1}(mod \ n) baab1(mod n)来表示。

Z n ∗ Z_{n}^{*} Zn的规模表示为 ϕ ( n ) \phi(n) ϕ(n)来表示。这个函数我们称为欧拉phi函数,满足:

ϕ ( n ) = n ∏ p : p 是 素 数 且 p ∣ n ( 1 − 1 p ) \phi(n) = n \prod_{p:p是素数且p \mid n}(1 - \frac{1}{p}) ϕ(n)=np:ppn(1p1)

p也可以叫n的素约数,例如45的素约数有3和5,带入公式等于24。说明模45的乘法群的规模是24,也说明从0-44中与45互质的数有24个。

如果n是素数,则n的素约数只有他自己,因此带入公式 ϕ ( n ) = n − 1 \phi (n) = n-1 ϕ(n)=n1

如果n是合数,则 ϕ ( n ) \phi (n) ϕ(n)的上界是n-1下界为

n e γ l n   l n n + 3 l n   l n n , n ≥ 3 \frac{n}{e^{\gamma}ln \ lnn+\frac{3}{ln \ lnn}},n \geq 3 eγln lnn+ln lnn3n,n3

此时 γ \gamma γ为0.577 215 664 9…称为欧拉常数。当n大于5时,存在更松弛的下界是

n 6   l n   l n n \frac{n}{6 \ ln \ ln n} 6 ln lnnn

3.3 子群

如果 ( S ′ , ⨁ ) (S',\bigoplus) (S,)中的元素都属于 ( S , ⨁ ) (S,\bigoplus) (S,),那么称 S ′ S' S S S S的子群。例如,在加法运算下,偶数形成整数的一个子群。

定理:一个有限群的非空运算封闭的一个群是一个有限群的子群。

拉格朗日群论定理:如果有限群S存在一个子群S’,那么|S’|是|S|的一个约数。

如果S’不等于S,那么S‘也称真子群

推论:如果S’是S的一个真子群,那么 ∣ S ′ ∣ ≤ ∣ S ∣ 2 |S'| \leq \frac{|S|}{2} S2S,因为如果想让|S’|最大化,又因为|S’|是|S|的一个约数,说明|S’|k=|S|,中另外一个约数k取2时候最大,因此有该推论。

3.4 由一个元素生成的子群

选择一个元素a,将a做k次运算, k ∈ Z k \in Z kZ,那么a可以生成一个子群,表示为:

a ( k ) = ⨁ i = 1 k a = a ⨁ a ⨁ a ⨁ ⋯ ⨁ a a^{(k)} = \bigoplus^{k}_{i = 1}a=a \bigoplus a \bigoplus a \bigoplus \dots \bigoplus a a(k)=i=1ka=aaaa

特别的,在模n的加法群 Z n Z_{n} Zn中,a生成的子群为 a ( k ) = k a   m o d   n a^{(k)}=ka \ mod \ n a(k)=ka mod n。在乘法群 Z n ∗ Z_{n}^{*} Zn中,a的生成子群为 a ( k ) = a k   m o d   n a^{(k)}=a^{k} \ mod \ n a(k)=ak mod n,其中由a生成的子群写作 < a > \left <a \right > a。a是生成元

元素生成子群具有封闭性,由运算的封闭性易知。

例如,在 Z 6 Z_{6} Z6中列举一些元素生成子群。

< 0 > = { 0 } < 1 > = { 0 , 1 , 2 , 3 , 4 , 5 } < 2 > = { 0 , 2 , 4 } \left < 0 \right > =\{0\} \\ \left < 1 \right > = \{0,1,2,3,4,5\} \\ \left < 2 \right > = \{0,2,4\} 0={0}1={0,1,2,3,4,5}2={0,2,4}

例如,在 Z 7 ∗ Z_{7}^{*} Z7中列举一些元素生成子群。

< 1 > = { 1 } < 2 > = { 1 , 2 , 4 } < 3 > = { 1 , 2 , 3 , 4 , 5 , 6 } \left < 1 \right > = \{1\} \\ \left < 2 \right > = \{1,2,4\} \\ \left < 3 \right > = \{1,2,3,4,5,6\} 1={1}2={1,2,4}3={1,2,3,4,5,6}

我们可以观察发现,子群中的元素一定包括单位元,且具有周期性。我们用 a ( 0 ) a^{(0)} a(0)表示单位元e。

定义:在群S中a的的定义为满足 a ( t ) = e a^{(t)} = e a(t)=e的最小的正整数t,用ord(a)来表示。

定理:a的生成子群的规模等于a的阶数。

推论:a的生成序列 a ( 1 ) , a ( 2 ) , a ( 3 ) , … , a ( n ) a^{(1)},a^{(2)},a^{(3)},\dots,a^{(n)} a(1),a(2),a(3),,a(n)具有周期性,其周期为t。子群等于一个周期的代表等价类,因此子群的规模数是t。并且 a ( p ) = a ( q ) a^{(p)} = a^{(q)} a(p)=a(q),当且仅当 p ≡ q   m o d   t p \equiv q \ mod \ t pq mod t

推论:在一个有限群S中, a ∈ S a \in S aS,则 a ( ∣ S ∣ ) = e a^{(|S|)} = e a(S)=e

证明:由拉格朗日群轮的行李可以知道, o r d ( a ) ∣ ∣ S ∣ ord(a) \mid |S| ord(a)S,因此 ∣ S ∣ ≡ 0   m o d   o r d ( a ) |S| \equiv 0 \ mod \ ord(a) S0 mod ord(a),因此 a ( ∣ S ∣ ) = a ( 0 ) = e a^{(|S|)} = a^{(0)} =e a(S)=a(0)=e


四、求解模线性方程

我们来考虑一个方程:已知a,b,n且 a > 0 , n > 0 a > 0,n > 0 a>0,n>0,求解x?

a x ≡ b ( m o d   n ) ax \equiv b(mod \ n) axb(mod n)

形如这样的方程,我们称为模n的线性方程

< a > \left < a \right > a为群 Z n Z_{n} Zn中a的生成子集,所以

< a > = { a ( k )   m o d   n } = { a k   m o d   n } \left < a \right > = \{ a^{(k)} \ mod \ n \} = \{ ak \ mod \ n \} a={a(k) mod n}={ak mod n}

因此我们可以知道x解存在的充分必要条件:

模n线性方程解的存在定理:解存在,当且仅当 b ∈ < a > b \in \left < a \right > ba

拉格朗日终极定理:对于任意整数 a a a n n n, a a a n n n模下的生成集的规模 ∣ < a > ∣ = n gcd ⁡ ( a , n ) | \left < a \right > | = \frac{n}{\gcd(a,n)} a=gcd(a,n)n

因为 a a a不一定是代表元素,但是 n n n一定是代表元素,并且 < a > = < d > \left < a \right > = \left < d \right > a=d,这是因为对于任意一个 a p ap ap,一定有一个 d q dq dq对应,这里 p p p q q q都是系数,因为 d d d a a a的约数,这是显然的。反过来 a a a也可以表示 d d d,因为 a x + n y = d ax+ny=d ax+ny=d,因此一定有 a x ≡ d m o d    n ax \equiv d \mod n axdmodn。(也称:裴蜀定理)。

进一步,我们有定理:对于任意正整数a和n,如果d = gcd(a,n),则在 Z n Z_{n} Zn中,

< a > = < d > = { 0 , d , 2 d , 3 d , … , ( ( n / d ) − 1 ) d } \left < a \right > = \left < d \right > = \{0,d,2d,3d,\dots,((n/d)-1)d\} a=d={0,d,2d,3d,,((n/d)1)d}

因此a元素生成子群的规模等于n/d。注意d的生成子群中等价类的代表元素不能大于等于n,因此有最大元素((n/d)-1)d。

模n线性方程解的存在定理2:解存在,当且仅当 d ∣ b d \mid b db,这里d=gcd(a,n)。这是因为,当b代表的等价类的代表元素 b   m o d   n ∈ < d > = { 0 , d , 2 d , 3 d , … , ( ( n / d ) − 1 ) d } b \ mod \ n \in \left < d \right > = \{0,d,2d,3d,\dots,((n/d)-1)d\} b mod nd={0,d,2d,3d,,((n/d)1)d},则d是b的一个约数。

解的个数推论:模n的线性方程要么有d个解,要么无解,这里d=gcd(a,n),注意这里的解指的是等价类,不是数,如果是数应该有无数个。

证明:如果有解,那么 b ∈ < d > b \in \left < d \right > bd,那么b一定是 { 0 , d , 2 d , 3 d , … , ( ( n / d ) − 1 ) d } \{0,d,2d,3d,\dots,((n/d)-1)d\} {0,d,2d,3d,,((n/d)1)d}中的一个元素,那么我们看看在x的可行域空间中[0,n-1]中,b出现了几次,就是解的个数,对应的下标元素也是解。又因为 ∣ < a > ∣ = n gcd ⁡ ( a , n ) | \left < a \right > | = \frac{n}{\gcd(a,n)} a=gcd(a,n)n,因此对于 i = 0 , 1 , 2 , 3 , ⋯   , n − 1 i=0,1,2,3,\cdots,n-1 i=0,1,2,3,,n1序列 a i m o d    n ai \mod n aimodn重复了 d d d次的周期,在每个周期内都有一个解,因此有 d d d个解。

n模的线性方程的特解定理:令(d,x’,y’)=extendedEuclid(a,n),有d=ax’+ny’。如果 d ∣ b d \mid b db,则线性方程组的一个特解为

x 0 = x ′ ( b / d )   m o d   n x_{0} = x'(b/d) \ mod \ n x0=x(b/d) mod n

证明:

因为 a x + n y = d ax+ny=d ax+ny=d,有 a x b d + n y b d = b \frac{axb}{d}+\frac{nyb}{d}=b daxb+dnyb=b,进一步 d d d能整除 b b b,因此有 a x b d ≡ b m o d    n \frac{axb}{d} \equiv b \mod n daxbbmodn,因此最小的一个解为 x 0 = x ′ ( b / d )   m o d   n x_{0} = x'(b/d) \ mod \ n x0=x(b/d) mod n

n模的线性方程的通解定理:得到一个x的任意一个特解 x 0 x_{0} x0之后,因此线性方程组共有d个解,分别是:

x i = x 0 + i ( n / d )   m o d   n , i ∈ { 0 , 1 , … , d − 1 } x_{i} = x_{0} + i(n/d) \ mod \ n,i \in \{0,1,\dots,d-1\} xi=x0+i(n/d) mod n,i{0,1,,d1}

证明:

得到了最小的解 x 0 x_{0} x0,加上序列的周期长度即可,即在 [ 0 , n − 1 ] [0,n-1] [0,n1]中遍历每一段周期的解。

因此我们可以写出如下代码:

void modularLinearEquationSolver(int a, int b, int n)
{
    // 求解exgcd(a,n)
    Res r = extendedEuclid(a, n);

    // 判断解的存在性
    if (b % r.d == 0)
    {
        // 求特解
        int x0 = (r.x * b / r.d) % n;
        // 求通解
        for (int i = 0; i < r.d; i++)
        {
            int xi = (x0 + i * n / r.d + n) % n;
            cout << xi << endl;
        }
    }
    else
    {
        cout << "No solutions" << endl;
    }
}

时间复杂度为O(lgn+gcd(a,n)),即递归加循环。

通过解定理,我们可以有如下推论:

推论:对于n>1且gcd(a,n)=1,那么方程有唯一解。否则无解。

通过以上算法,我们求a的逆元也很好求,只需令b=1。若a在乘法群中,即a与n互质,那么gcd(a,n)=1,由上述推论可知,方程一定有解,且解唯一,故a的逆元一定唯一。

逆元求法推论:如果gcd(a,n)=1,那么,方程 a x ≡ 1   ( m o d   n ) ax \equiv 1 \ (mod \ n) ax1 (mod n)的唯一解就是extendedEuclid(a,n)返回的x,因为d = 1,xa+ny=1,所以 a x ≡ 1   ( m o d   n ) ax \equiv 1 \ (mod \ n) ax1 (mod n),所以x就是方程的唯一解。


五、中国剩余定理

中国剩余定理:令 n = n 1 n 2 … n k n=n_{1}n_{2} \dots n_{k} n=n1n2nk,其中因子 n i n_{i} ni两两互质,考虑如下对应关系:

a ↔ ( a 1 , a 2 , … , a k ) a \leftrightarrow (a_{1},a_{2}, \dots ,a_{k}) a(a1,a2,,ak)

这里 a ∈ Z n , a i ∈ Z n i a \in Z_{n},a_{i} \in Z_{n_{i}} aZn,aiZni,而对于 i = 1 , 2 , … , k i=1,2,\dots,k i=1,2,,k

a i = a   m o d   n i a_{i} = a \ mod \ n_{i} ai=a mod ni

理解:类比于坐标系统, n = n 1 n 2 … n k n=n_{1}n_{2} \dots n_{k} n=n1n2nk可以看做是一组基底,而对于每一个 a ∈ Z n a \in Z_{n} aZn,a都可以用这一组基底用一个k元组的坐标形式表示。

类比于向量,中国剩余定理也可以进行类似的相加,相减,相乘运算。

那么:

( a + b )   m o d   n ↔ ( ( a 1 + b 1 )   m o d   n , ( a 2 + b 2 )   m o d   n , … , ( a k + b k )   m o d   n ) ( a − b )   m o d   n ↔ ( ( a 1 − b 1 )   m o d   n , ( a 2 − b 2 )   m o d   n , … , ( a k − b k )   m o d   n ) ( a b )   m o d   n ↔ ( ( a 1 b 1 )   m o d   n , ( a 2 b 2 )   m o d   n , … , ( a k b k )   m o d   n ) (a+b) \ mod \ n \leftrightarrow ((a_{1}+b_{1}) \ mod \ n,(a_{2}+b_{2}) \ mod \ n,\dots,(a_{k}+b_{k}) \ mod \ n) \\ (a-b) \ mod \ n \leftrightarrow ((a_{1}-b_{1}) \ mod \ n,(a_{2}-b_{2}) \ mod \ n,\dots,(a_{k}-b_{k}) \ mod \ n) \\ (ab) \ mod \ n \leftrightarrow ((a_{1}b_{1}) \ mod \ n,(a_{2}b_{2}) \ mod \ n,\dots,(a_{k}b_{k}) \ mod \ n) \\ (a+b) mod n((a1+b1) mod n,(a2+b2) mod n,,(ak+bk) mod n)(ab) mod n((a1b1) mod n,(a2b2) mod n,,(akbk) mod n)(ab) mod n((a1b1) mod n,(a2b2) mod n,,(akbk) mod n)

证明:

从a转换到 a i a_{i} ai是相当直接的,做k次模运算即可。

我们将讨论如何从 a i a_{i} ai转换到a。

我们类比于线性代数中,坐标的过度矩阵变换,类似的,我们也可以找到模坐标系统下的单位阵。例如:我们计算 e 1 = ( 1 , 0 , 0 , … , . . . , 0 ) e_{1}=(1,0,0,\dots,...,0) e1=(1,0,0,,...,0),由这个公式可以说明,存在一个数M,使得M除以 n 1 n_{1} n1的余数是1,除以其他的余数均为0,也就是说,这个是数是其他 n i n_{i} ni的公倍数,并且除以 n 1 n_{1} n1的余数是1。

因此,我们定义 m 1 = n 2 n 3 n 4 … n k m_{1}=n_{2}n_{3}n_{4}\dots n_{k} m1=n2n3n4nk,也就是说,定义 m i = n 1 … n i − 1 n i + 1 … n k m_{i}=n_{1}\dots n_{i-1} n_{i+1} \dots n_{k} mi=n1ni1ni+1nk,除了 n i n_{i} ni的q其余k-1项的乘积,满足是其余k-1项的公倍数。

又因为唯一素因子分解定理的推论可以知道, m i m_{i} mi一定与 n i n_{i} ni互斥,因此在模 n i n_{i} ni下,一定存在 m i m_{i} mi的唯一逆元 m i − 1   m o d   n i m_{i}^{-1} \ mod \ n_{i} mi1 mod ni,又因为逆元乘以该数就是单位元,因此定义 c i = m i ( m i − 1   m o d   n i ) c_{i} = m_{i} (m_{i}^{-1} \ mod \ n_{i}) ci=mi(mi1 mod ni),故 c i ≡ 1   m o d   n i c_{i} \equiv 1 \ mod \ n_{i} ci1 mod ni,且 c i c_{i} ci也是其余k-1项的公倍数,也就是我们要找的M。

最后,我们再线性展开求解a即可,因此:

a ≡ ∑ i = 1 k a i c i   ( m o d   n ) a \equiv \sum_{i=1}^{k} a_{i}c_{i} \ (mod \ n) ai=1kaici (mod n)

因此,我们就可以计算出解a。这就是中国剩余定理。应用可以把一个较大的数按照一些质数的余数分解出坐标,按照坐标运算计算量会比直接计算要小很多。

我们也有下面两个推论:

推论(中国剩余定理的唯一解性):如果 n 1 , … , n k n_{1},\dots,n_{k} n1,,nk,两两互质,那么对于任意k个整数 a 1 , … , a k a_{1},\dots,a_{k} a1,,ak,模线性方程组

x ≡ a i ( m o d   n i ) , i = 1 , 2 , … , k x \equiv a_{i} (mod \ n_{i}),i=1,2,\dots,k xai(mod ni),i=1,2,,k

有唯一解。

推论(数量坐标):如果 n 1 , … , n k n_{1},\dots,n_{k} n1,,nk,两两互质,对于任意整数a,那么

x ≡ a ( m o d   n i ) x \equiv a (mod \ n_{i}) xa(mod ni)

当且仅当

x ≡ a ( m o d   n ) x \equiv a (mod \ n) xa(mod n)


六、元素的幂

6.1 欧拉、费马定理

对于加法群下的模的线性方程我们已经讨论的差不多了,我们讨论一下在乘法群下非线性的模的幂方程。

定义:令 < a > \left < a \right > a表示由元素a反复相乘形成的 Z n ∗ Z_{n}^{*} Zn子群,令 o r d n ( a ) ord_{n}(a) ordn(a)为子群的阶,经过合理类推,a元素的生成序列也是具有周期性的,用欧拉phi函数表示 Z n ∗ Z_{n}^{*} Zn的规模,把前面的定理转换一下得到欧拉定理,具体一下,用 Z p ∗ Z_{p}^{*} Zp表示 Z n ∗ Z_{n}^{*} Zn下素数形成的子群,得到费马定理。

推论:在一个有限群S中, a ∈ S a \in S aS,则 a ( ∣ S ∣ ) = e a^{(|S|)} = e a(S)=e

欧拉定理:对于任意的整数 n > 1 n>1 n>1 a ϕ ( n ) ≡ 1 ( m o d   n ) a^{\phi(n)} \equiv 1(mod \ n) aϕ(n)1(mod n) ∀ a ∈ Z n ∗ \forall a \in Z_{n}^{*} aZn成立。

费马定理:对于任意的整数 p p p是素数, a p − 1 ≡ 1 ( m o d   p ) a^{p-1} \equiv 1(mod \ p) ap11(mod p) ∀ a ∈ Z p ∗ \forall a \in Z_{p}^{*} aZp成立。

扩展欧拉定理

a b ≡ { a b   m o d   φ ( p ) ,   gcd ⁡ ( a ,   p ) = 1 a b , gcd ⁡ ( a ,   p ) ≠ 1 ,   b < φ ( p ) a b   m o d   φ ( p ) + φ ( p ) , gcd ⁡ ( a ,   p ) ≠ 1 ,   b ≥ φ ( p ) ( m o d p ) a^b\equiv \begin{cases} a^{b\bmod\varphi(p)},\,&\gcd(a,\,p)=1\\ a^b,&\gcd(a,\,p)\ne1,\,b<\varphi(p)\\ a^{b\bmod\varphi(p)+\varphi(p)},&\gcd(a,\,p)\ne1,\,b\ge\varphi(p) \end{cases} \pmod p ababmodφ(p),ab,abmodφ(p)+φ(p),gcd(a,p)=1gcd(a,p)=1,b<φ(p)gcd(a,p)=1,bφ(p)(modp)

相信对上面的学习,证明这两个定理不难证明。

特别的,因为0不是素数,因此费马定理对 Z p Z_{p} Zp中除了0的元素都适用,当 a ∈ Z p a \in Z_{p} aZp的时候,如果p是素数,那么 a p ≡ a ( m o d   p ) a^{p} \equiv a ( mod \ p) apa(mod p),这是因为 a p − 1 a^{p-1} ap1是单位元,任何数乘以单位元仍等于本身。

如果 o r d n ( g ) = ∣ Z n ∗ ∣ ord_{n}(g)=|Z_{n}^{*}| ordn(g)=Zn,的对于模n来说, Z n ∗ Z_{n}^{*} Zn中的每一个元素都是g的幂次项,我们称g是 Z n ∗ Z_{n}^{*} Zn的一个原根生成元。如果群 Z n ∗ Z_{n}^{*} Zn有原根,那么就称群是循环的

循环群定理:对所有的素数p>2,和所有的正整数e,使得 Z n ∗ Z_{n}^{*} Zn循环的n>1有 2 , 4 , p e , 2 p e 2,4,p^{e},2p^{e} 2,4,pe,2pe

如果g是 Z n ∗ Z_{n}^{*} Zn上的一个原根, ∀ a ∈ Z n ∗ , ∃ k ∈ Z , g k ≡ a ( m o d   n ) \forall a \in Z_{n}^{*},\exist k \in Z,g^{k} \equiv a(mod \ n) aZn,kZ,gka(mod n),这个k称为对模n到基g上的a的一个离散对数指数,将这个值表示为 i n d n , g ( a ) ind_{n,g}(a) indn,g(a)

离散对数定理:如果g是 Z n ∗ Z_{n}^{*} Zn上的一个原根,则当且仅当等式 x ≡ y ( m o d   ϕ ( n ) ) x \equiv y(mod \ \phi(n)) xy(mod ϕ(n))成立时,有等式 g x ≡ g y ( m o d   n ) g^{x} \equiv g^{y} (mod \ n) gxgy(mod n)成立。

定理:如果p是一个奇素数且 e ≥ 1 e \geq 1 e1,则方程

x 2 ≡ 1 ( m o d   p e ) x^{2} \equiv 1 (mod \ p^{e}) x21(mod pe)

仅有两个解,即为x=1和x=-1。我们称为平凡平方根

推论:如果对模n存在1的非平凡平方根,则n是合数。

6.2 用反复平方法求数的幂

在实际问题中,经常出现一种运算,就是求一个数的幂然后对另外一个数的模,也称为模取幂。就是求 a b m o d   n a^{b} mod \ n abmod n的值,其中a和吧都是非负整数,n是一个正整数。采用b的二进制表示,反复平方法可以高效的解决问题。

// 'int' is a 32-bits integer
// from high bit to low bit
int modularExponentiation(int a, int b, int n)
{
    int c = 0;
    int d = 1;
    int digit = 32;
    while (digit--)
    {
        d = (d * d) % n;
        c = 2 * c;
        if ((b >> digit) & 1)
        {
            d = (d * a) % n;
            c = c + 1;
        }
    }
    return d;
}

我们用循环不变式的方式来解释这段代码的正确性。将b拆解为二进制序列为 ( b k , b k − 1 , … , b 1 ) (b_{k},b_{k-1},\dots,b_{1}) (bk,bk1,,b1),其中 b k b_{k} bk为最高位, b 1 b_{1} b1为最低位。c为b序列前几个元素组成子序列的值。

初始化:此时c即b序列的前缀是空的,所以c为0。 d = 1 = a 0   m o d   n d=1=a^{0} \ mod \ n d=1=a0 mod n

保持:令c’和d’表示当前循环结束时候的c和d值,也就是下一次循环时候c和d的初始值。每次迭代更新 c ′ = 2 c c'=2c c=2c如果该位上的b是0, c = 2 c + 1 c=2c+1 c=2c+1如果该位上的b是1的话。再来看d,如果该位上的b是0, d ′ = d ⋅ d   m o d   n = a c ⋅ a c   m o d   n = d 2   m o d   n = a 2 c   m o d   n = a c ′   m o d   n d'=d \cdot d \ mod \ n=a^{c} \cdot a^{c} \ mod \ n=d^{2} \ mod \ n = a^{2c} \ mod \ n=a^{c'} \ mod \ n d=dd mod n=acac mod n=d2 mod n=a2c mod n=ac mod n;如果该位上的b为1的话, d ′ = a 2 c ⋅ a   m o d   n = a 2 c + 1   m o d   n = a c ′   m o d   n d'=a^{2c} \cdot a \ mod \ n=a^{2c+1} \ mod \ n=a^{c'} \ mod \ n d=a2ca mod n=a2c+1 mod n=ac mod n

终止:此时digit–的值为0,已经遍历完所有的二进制位,while循环退出。

注意此算法里面c变量不是必须的。

我们也可以写出一个从低位到高位迭代的算法:

// 'int' is a 32-bits integer
// from low bit to high bit
int modularExponentiation(int a, int b, int n)
{
    int c = 0;
    int d = 1;
    int digit = 1;
    int q = a;
    while (b)
    {
        c = c | ((b & 1) * digit);
        if (b & 1)
        {
            d = (d * q) % n;
        }
        digit = digit << 1;
        q = (q * q) % n;
        b = b >> 1;
    }
    return d;
}

七、RSA公钥加密系统

此章节属于数论应用,不属于本文讨论范围之内,故略去,今后可能会在信息安全部分补充上。


八、素数测试

8.1 素数的密度

定义:素数分布函数 π ( n ) \pi(n) π(n)描述了小于或等于n的素数的个数,素数定理给出了一个 π ( n ) \pi(n) π(n)一个比较重要的结论。

素数定理

lim ⁡ n → ∞ π ( n ) n / ln ⁡ n = 1 \lim_{n \to \infty} \frac{\pi(n)}{n/\ln n} = 1 nlimn/lnnπ(n)=1

接下来,我们将对对于一个大整数n,判断他是否为素数这个问题展开讨论。根据唯一素因子分解定理,一个n>1的正整数,可以分解为唯一形式的几个素数相乘,如果n是素数,当且仅当n仅仅能分解为本身,且指数为一,否则,如果n能被比他小的素数整除,那么n就是合数,我们称这种方法叫试除,简单的,我们可以从2开始遍历一直试除到 ⌊ n ⌋ \left \lfloor \sqrt{n} \right \rfloor n ,大于2的偶数不要。但是通常这种做法效率不高,我们要找到一个高性能的素数测试方法。

8.2 基于费马定理的伪素数测试

费马定理:对于任意的整数 p p p是素数, a p − 1 ≡ 1 ( m o d   p ) a^{p-1} \equiv 1(mod \ p) ap11(mod p) ∀ a ∈ Z p ∗ \forall a \in Z_{p}^{*} aZp成立。

那么我们可以任取一个a,令 a ∈ Z p ∗ a \in Z_{p}^{*} aZp,我们通过上面的反复平方法计算幂的模,即可判断p是不是素数了。

但是,我们用到的是费马定理的必要条件,而费马定理只说明了充分条件的正确性,必要条件不一定成立。我们把满足必要条件,并且p是一个合数的数,称为基为a的伪素数。如果我们要严格验证p是否为素数,那么我们要验证所有的a都成立才行。

下面的过程就是基于这种方法测试n素性的过程:

bool pseudoPrime(int n)
{
    return modularExponentiation(2, n - 1, n);
}

以2为基进行素性测试,这个过程很少产生错误,但也只有一种类型的错误。也就是,如果他返回false,那么n必定是合数,如果他返回true,那么结果有时候会出错。

这个错误的概率有多大?机会非常少。在小于10 000的n值中,只有341,561,645,1105…,这22个值判断失败,而且n值越大判断失败的概率就越小,总之这种方法可以用于判断大数上,基本不会出错。

同理,即便我们切换了a的值,例如3,也不可能完全消除错误。总之,合数n对于所有的 a ∈ Z n ∗ a \in Z_{n}^{*} aZn都满足费马定理等式成立的,他们被称为Carmichael数。Carmichael数很少见,前三个分别是561,1105,1729。在小于100 000 000的数中,Carmichael数也只有255个。也就是说,上述方法在判断Carmichael数的素性的时候,必然会出错。

接下来,我们将对这种方法进行改进,避开Carmichael数的错误。

8.3 Miller-Rabin 随机性素数测试法

Miller-Rabin算克服了两个问题:

  • 随机多次选择基底a进行测试,减小了出错的可能。
  • 运用二次探测定理,探测寻找一个以模n为底1的非凡平方根。可以排除掉Carmichael数的干扰。

首先我们定义函数witness

bool witness(int a, int n)
{
    int u = n - 1;
    int t = 0;

    while ((u & 1) != 0)
    {
        t++;
        u = u >> 1;
    }

    int x0 = modularExponentiation(a, u, n);

    for (int i = 0; i <= t; i++)
    {
        int xi = (x0 * x0) % n;
        if (xi == 1 && x0 != 1 && x0 != n - 1)
        {
            return true;
        }
        x0 = xi;
    }

    if (x0 != 1)
        return true;
    return false;
}

首先我们令 n − 1 = 2 t u n-1=2^{t}u n1=2tu,也就是说将n-1按二进制分解为一个奇数后面带了t个零,很容易理解。之后我们计算 x 0 = a u   m o d   n x_{0} = a^{u} \ mod \ n x0=au mod n,之后我们进行反复平方,计算 x 1 = a 2 u   m o d   n = a u a u   m o d   n = x 0 2   m o d   n x_{1} = a^{2u} \ mod \ n=a^{u}a^{u} \ mod \ n=x_{0}^{2} \ mod \ n x1=a2u mod n=auau mod n=x02 mod n x 2 = a 2 2 u   m o d   n = a 2 u a 2 u   m o d   n = x 1 2   m o d   n x_{2} = a^{2^{2}u} \ mod \ n=a^{2u}a^{2u} \ mod \ n=x_{1}^{2} \ mod \ n x2=a22u mod n=a2ua2u mod n=x12 mod n,依次类推。直到计算 x t = a 2 t u   m o d   n = a n − 1   m o d   n x_{t} = a^{2^{t}u} \ mod \ n=a^{n-1} \ mod \ n xt=a2tu mod n=an1 mod n

在迭代计算中,根据二次探测定理:

定理:如果p是一个奇素数且 e ≥ 1 e \geq 1 e1,则方程
x 2 ≡ 1 ( m o d   p e ) x^{2} \equiv 1 (mod \ p^{e}) x21(mod pe)
仅有两个解,即为x=1和x=-1。

如果 x i x_{i} xi取模的值为1,但是 x i − 1 x_{i-1} xi1取模的值不是1也不是-1,那么就说明 x i − 1 x_{i-1} xi1就是该方程的非平凡平方根。结果是显然的,n一定不是素数,即n一定是合数,因此返回true。

最后根据费马定理,如果 x t = a n − 1 ≠ 1 ( m o d   n ) x_{t} = a^{n-1} \neq 1 (mod \ n) xt=an1=1(mod n)那么说明n不满足费马定理,n一定是合数,返回true,否则返回false。

加上随机性测试,我们得到Miller-Rabin 随机性素数测试法

bool millerRabin(int n, int cnt)
{
    for (int i = 0; i < cnt; i++)
    {
        int a = rand() % (n - 1) + 1;
        if (witness(a, n))
            return false;
    }
    return true;
}

我们测试cnt次,每次随机取a进行测试。出错率能有多小呢,不取决于n的值,而是取决于cnt的次数,和每次抽取a的情况,如果cnt足够大,a足够“好”,那么出错的概率将及其渺小。因为篇幅原因,就不展开对出错率的计算了,有兴趣的读者可以参考《算法导论》。


九、整数的因子分解

现在我们想分解一个大整数按照唯一素因子分解定理去分解,进行因子分解。这对于素数来说,只需要执行一次素性测试即可,而对于合数来说,往往进行因子分解比素性测试还要困难。

9.1 Pollard的rho启发式方法

对小于R的任意整数进行试除,就能获取小于 R 2 R^2 R2的任意整数的因子分解。下面的过程用相同的工作量,就能对小于 R 4 R^{4} R4的任意整数进行因子分解(除非运气不佳)。由于该过程仅仅是一种启发式算法,因此既不能保证其运行时间也不能保证能成功运行,但他只使用固定的储存空间。

void pollardRho(int n)
{
    int i = 1;
    int x = rand() % n;
    int y = x;
    int k = 2;
    while (1)
    {
        i = i + 1;
        x = (x * x - 1) % n;
        int d = euclid(y - x, n);
        if (d != 1 && d != n)
        {
            cout << d << endl;
        }
        if (i == k)
        {
            y = x;
            k = 2 * k;
        }
    }
}

这个算法义在于在 [ 0 , n − 1 ] [0,n-1] [0,n1]中取遍尽可能多的且对于下面计算d来说最有可能的因子的情况,因此我们有生成序列

x i = x i − 1 2   m o d   n x_{i} = x_{i-1}^{2} \ mod \ n xi=xi12 mod n

我们可以近似的把 x i x_{i} xi看做是随机数生成器,但是产生的序列都是比较有帮助与产生n的因子d。

而y变量则保存下标是2的幂次的 x 2 k x_{2^{k}} x2k的值,每次循环计算gcd(y-x,n)的因子,如果因子不是平凡因子,那么就输出这个因子d的值。

并且,这个x序列是一个带环的链表。总是会进入环中无限的循环下去,因此我们不能保证这个算法能够有效执行,仅仅是输出可能的因子。

十、其他定理

  • 伯特兰—切比雪夫定理:若整数 n > 3 n > 3 n>3,则至少存在一个质数 p p p,符合 n < p < 2 n − 2 n < p < 2n − 2 n<p<2n2。另一个稍弱说法是:对于所有大于 1 1 1的整数 n n n,至少存在一个质数 p p p,符合 n < p < 2 n n < p < 2n n<p<2n
  • 拉格朗日四平方定理:任意的一个正整数都可以用四个完全平方数表示,例如: 123 = 8 2 + 5 2 + 5 2 + 3 2 123 = 8^2+5^2+5^2+3^2 123=82+52+52+32
  • 齐肯多夫定理:表示任何正整数都可以表示成若干个不连续的斐波那契数(不包括第一个斐波那契数)之和。
  • 威尔逊定理:若 p p p是素数,则 ( p − 1 ) ! ≡ − 1 m o d    p (p-1)! \equiv -1 \mod p (p1)!1modp,反之也成立。
  • 毕达哥斯拉定理:毕达哥斯拉三角形的三边长都是整数,并且是直角三角形,即 a 2 + b a = c 2 a^2+b^a=c^2 a2+ba=c2。如果 a b c abc abc三个数互质,那么这个三角形是基本毕达哥斯拉三角形,任意一个毕达哥斯拉三角形都是由基本毕达哥斯拉三角形的倍数生成。欧几里得法则给出了生成基本毕达哥斯拉三角形的方法: ( n 2 − m 2 , 2 n m , n 2 + m 2 ) (n^2-m^2,2nm,n^2+m^2) (n2m2,2nm,n2+m2),这里 0 < m < n 0<m<n 0<m<n n n n m m m至少一个是奇数。

总结

本文对《算法导论》一书中数论部分做了一个粗略的总结,加上笔者一点的见解。光光学习理论知识是不够的,我们还必须付之于题目与实际当中,多刷题才能AC全场。以后该专题也会记录一下数论相关的题目与解法以及补充内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值