【密码学基础】02 数论基础

  数论是研究整数性质的学科,在密码学中广泛应用了数论中一些重要结论,比如素数、离散对数问题等。数论的概念和结论都比较抽象,而且涉及大量的证明,初学时忽略这些细节,而涉及到具体密码算法时掌握更多的细节或许是合理的学习方法。下面将介绍数论中的主要内容,包括整除的整除和同余、素数的基本性质和应用等。

更新历史:

  • 2021年07月18日完成初稿

  数论的知识是比较抽象的,对于只需要简单的数论背景知识的初学者而言,显然长篇大论般的理论和证明是不利于学习的,因此在这里将数论基础分为了「基础篇」和「扩展篇」,基础篇省去了定理的扩展描述和证明,而扩展篇则增加了数论知识的广度和深度,对于初学者而言可以自学习基础篇了解数论中的几个基本概念即可,等到后面涉及数论知识点后重新翻看基础篇和扩展篇即可。

基础篇

  在密码学中,最重要的两大块数论基础知识为整除和同余、素数及其定理,下面将简单介绍关于数论基础知识。

1. 整除和同余

  整除是小学阶段的概念,对此不多介绍,只介绍数论中整除的定义与使用的符号。

  • 整除:设 a , b , m ∈ Z a, b, m\in Z a,b,mZ ∃ m \exists m m使得 a = m b a = mb a=mb成立,则称非零整数 b b b整除 a a a,记作 b ∣ a b|a ba,此时称 b b b a a a的因子, a a a b b b的倍数。举一些例子,比如 2 ∣ 6 , 3 ∣ 6 2|6, 3|6 26,36等。

除数与被除数
  需要熟知一个容易混淆的概念,被除数    ÷    \;\div\; ÷除数    =    \;=\; =商…余数,因此整除描述了「除数」整除「被除数」的情况,比如 6    ÷    3 = 2......0 6\;\div\;3=2......0 6÷3=2......0,描述了 3 3 3整除 6 6 6的情况,在中文中除和除以是不同的概念,一定要区分好。

  在上面,假设有 m ∣ a    , m ∣ b m|a\;,m|b ma,mb说明 m m m a a a的因子,也是 b b b的因子,因此称 m m m a a a b b b的公因子,由于 1 1 1是任何整数的因子,故公因子一定存在(至少为 1 1 1),而令人感兴趣的是两个整数的最大公因子(Greatest Common Divisor)是多少。

  • 最大公因子:设 a , b , m ∈ Z a, b, m \in Z a,b,mZ,而且 m ∣ a , m ∣ b m|a, m|b ma,mb,若 m m m是整除 a a a b b b的最大整数,那么 m m m称为 a a a b b b的最大公因子,记作 m = g c d ( a , b ) m = gcd(a, b) m=gcd(a,b)

互素
  利用最大公因子,可以定义一个常用的概念,即互素:称整数 a , b a,b a,b是互素的,当且仅当 g c d ( a , b ) = 1 gcd(a,b)=1 gcd(a,b)=1

  求解最大公因子有非常有效的算法——欧几里得算法(Euclidean Algorithm),不过欧几里得算法利用了余数的概念,因此下面先介绍余数的概念。整除理解起来还比较简单,在带余除法中定义了余数的概念:

  • 带余除法 ∀ n ∈ Z + \forall n \in Z^+ nZ+ ∀ a ∈ Z \forall a \in Z aZ ∃ q , r ∈ Z \exists q,r \in Z q,rZ 0 ≤ r < n 0\leq r <n 0r<n使得 a = q n + r a=qn+r a=qn+r,其中 q = ⌊ a / n ⌋ q=\lfloor a/n \rfloor q=a/n ⌊ ⌋ \lfloor \rfloor 为向下取整。

  可以看到,其中的 q q q即为商,而 r r r即为余数,按照上面的公式有 r = a − ⌊ a / n ⌋ × n r=a-\lfloor a/n \rfloor \times n r=aa/n×n,在这里用一个更加简洁的符号表达 r r r,那就是模运算符号 m o d mod mod,记作 r = a    m o d    n r=a\;mod\;n r=amodn,这里称 n n n是模数,该运算称为模 n n n运算。

  回到求解最大公因子,对于任意整数 a a a b b b可以通过下面的方式计算 g c d ( a , b ) gcd(a,b) gcd(a,b),不断使用带余除法,直至余数为 0 0 0,此时的除数即为最大公因子,即有下面的过程

a = q 1 b + r 1      ( 0 < r 1 < b ) b = q 2 r 1 + r 2 ( 0 < r 2 < r 1 ) r 1 = q 3 r 2 + r 3 ( 0 < r 3 < r 2 ) . . . r n − 2 = q n r n − 1 + r n ( 0 < r n < r n − 1 ) r n − 1 = q n + 1 r n + 0 ⇒ g c d ( a , b ) = r n a = q_1b + r_1\qquad\;\;(0<r_1<b)\\ b = q_2r_1 + r_2\qquad(0<r_2<r_1)\\ r_1 = q_3r_2 + r_3\qquad(0<r_3<r_2)\\ ...\\ r_{n-2} = q_nr_{n-1} + r_n\quad(0<r_n<r_{n-1})\\ r_{n-1}=q_{n+1}r_n+0\quad \Rightarrow gcd(a,b)=r_n\\ a=q1b+r1(0<r1<b)b=q2r1+r2(0<r2<r1)r1=q3r2+r3(0<r3<r2)...rn2=qnrn1+rn(0<rn<rn1)rn1=qn+1rn+0gcd(a,b)=rn

  欧几里得算法证明并利用了等式: g c d ( a , b ) = g c d ( b , r 1 ) = . . . = g c d ( r n − 1 , r n ) = g c d ( r n , 0 ) = r n gcd(a,b) = gcd(b,r_1)=...=gcd(r_{n-1},r_n)=gcd(r_n,0)=r_n gcd(a,b)=gcd(b,r1)=...=gcd(rn1,rn)=gcd(rn,0)=rn。下面是欧几里得算法的实现:

# 利用Euclid算法计算最小公因数gcd(a, b)
def Euclid_gcd(a, b):
    r1 = max(abs(a), abs(b))     # 令r1等于绝对值大的数
    r2 = min(abs(a), abs(b))     # 令r2等于绝对值小的数
    if r2 == 0:
        return r1
    else:
        return Euclid_gcd(r2, r1%r2)

  尽管整除是一种很好的性质,但不是所有整数都具备,大部分情况而言,对于两个整数相除还是会存在余数。注意到一种情况,两个不同的数 a , b a,b a,b都是除以另一个数 n n n可能获得相同的余数,这种情况称为关于模 n n n是同余的:

  • 同余:若 a    m o d    n = b    m o d    n a\;mod\;n=b\;mod\;n amodn=bmodn,那么称整数 a a a b b b是模 n n n同余的,记作 a ≡ b ( m o d    n ) a\equiv b(mod\;n) ab(modn)

  同余运算中,最重要的是模数 n n n,比如 6 6 6 11 11 11 5 5 5同余,而模 3 3 3就不同余了。因此考虑一般情况,对于模 n n n运算,考察所有整数 Z = { 0 , ± 1 , ± 2 , ± 3 , . . . } Z=\{0, \pm 1, \pm 2, \pm 3, ...\} Z={ 0,±1,±2,±3,...} ∀ a ∈ Z \forall a\in Z aZ,根据定义 a    m o d    n ∈ { 0 , 1 , 2 , . . . , n − 1 } a\;mod\;n\in \{0, 1, 2,..., n-1\} amodn{ 0,1,2,...,n1},因此对于任何整数只要进行模 n n n运算之后,所有整数都被限制到有限的集合中,那么必然会出现同余的情况,依据此可以定义下面两个概念:

  • 剩余类集:模 n n n运算的所有余数的集合,记作 Z n = { 0 , 1 , 2 , . . . , n − 1 } Z_n=\{0, 1, 2,..., n-1\} Zn={ 0,1,2,...,n1}
  • 剩余类:所有模 n n n同余的整数的集合,一般用最小的非负整数作为代表,记作 [ 0 ] , [ 1 ] , [ 2 ] , . . , [ n − 1 ] [0],[1],[2],..,[n-1] [0],[1],[2],..,[n1]

  下面举一个例子:计算 ∀ a ∈ Z ,    a    m o d    3 \forall a\in Z,\;a\;mod\;3 aZ,amod3
. . . , − 9 , − 6 , − 3 , 0 , 3 , 6 , 9 , . . .    m o d    3 = 0 . . . , − 8 , − 5 , − 2 , 1 , 4 , 7 , 10 , . . .    m o d    3 = 1 . . . , − 7 , − 4 , − 1 , 2 , 5 , 8 , 11 , . . .    m o d    3 = 2 ..., -9, -6, -3, 0, 3, 6, 9, ...\;mod\;3=0\\ ..., -8, -5, -2, 1, 4, 7, 10, ...\;mod\;3=1\\ ..., -7, -4, -1, 2, 5, 8, 11, ...\;mod\;3=2\\ ...,9,6,3,0,3,6,9,...mod3=0...,8,5,2,1,4,7,10,...mod3=1...,7,4,1,2,5,8,11,...mod3=2

  则 Z 3 = { 0 , 1 , 2 } Z_3=\{0, 1, 2\} Z3={ 0,1,2},而剩余类有 3 3 3个,分别是:
[ 0 ] = { . . . , − 9 , − 6 , − 3 , 0 , 3 , 6 , 9 , . . . } [ 1 ] = { . . . , − 8 , − 5 , − 2 , 1 , 4 , 7 , 10 , . . . } [ 2 ] = { . . . , − 7 , − 4 , − 1 , 2 , 5 , 8 , 11 , . . . } [0]=\{..., -9, -6, -3, 0, 3, 6, 9, ...\}\\ [1]=\{..., -8, -5, -2, 1, 4, 7, 10, ...\}\\ [2]=\{..., -7, -4, -1, 2, 5, 8, 11, ...\}\\ [0]={ ...,9,6,3,0,3,6,9,...}[1]={ ...,8,5,2,1,4,7,10,...}[2]={ ...,7,4,1,2,5,8,11,...}

  上面讲述了很多同余的概念,之所以关注这些是为了进行剩余类上的模运算:

  • 模运算:称二元运算 a    m o d    n = r a\;mod\;n=r amodn=r是模 n n n运算, r r r a a a n n n的值,且 0 ≤ r < n 0\leq r <n 0r<n

  可以证明对于任意两个整数 a a a b b b有下面的结论,即:

  • [ ( a    m o d    n ) + ( b    m o d    n ) ]    m o d    n = ( a + b )    m o d    n [(a\;mod\;n)+(b\;mod\;n)]\;mod\;n=(a+b)\;mod\;n [(amodn)+(bmodn)]modn=(a+b)modn
  • [ ( a    m o d    n ) − ( b    m o d    n ) ]    m o d    n = ( a − b )    m o d    n [(a\;mod\;n)-(b\;mod\;n)]\;mod\;n=(a-b)\;mod\;n [(amodn)(bmodn)]modn=(ab)modn
  • [ ( a    m o d    n ) × ( b    m o d    n ) ]    m o d    n = ( a × b )    m o d    n [(a\;mod\;n)\times (b\;mod\;n)]\;mod\;n=(a\times b)\;mod\;n [(amodn)×(bmodn)]modn=(a×b)modn
  • 加法交换律 ( a + b )    m o d    n = ( b + a )    m o d    n (a+b)\;mod\;n=(b+a)\;mod\;n (a+b)modn=(b+a)modn
  • 乘法交换律 ( a × b )    m o d    n = ( b × a )    m o d    n (a\times b)\;mod\;n=(b\times a)\;mod\;n (a×b)modn=(b×a)modn
  • 加法消去律 a + b = a + c ⇒ b = c    ( m o d    n ) a+b=a+c\Rightarrow b=c\;(mod\;n) a+b=a+cb=c(modn)
  • 乘法消去律 a a a在模 n n n运算中存在乘法逆元时): ∀ a ≠ 0 , a × b = a × c ⇒ b = c    ( m o d    n ) \forall a\neq 0, a\times b=a\times c\Rightarrow b=c\;(mod\;n) a=0,a×b=a×cb=c(modn)

  消去律的成立与否与逆元的存在与否有很大关系,下面是加法逆元和乘法逆元的定义:

  • 加法逆元 a , b ∈ Z n a,b\in Z_n a,bZn,若 ( a + b )    m o d    n = 0 (a+b)\;mod\;n=0 (a+b)modn=0,则 a a a b b b互为加法逆元,记 a a a的加法逆元为 − a -a a
  • 乘法逆元 a , b ∈ Z n a,b\in Z_n a,bZn,若 ( a × b )    m o d    n = 1 (a\times b)\;mod\;n=1 (a×b)modn=1,则 a a a b b b互为乘法逆元,记 a a a的乘法逆元为 a − 1 a^{-1} a1

  由于加法逆元一定存在,故加法消去律一定成立,而但当且仅当 g c d ( a , n ) = 1 gcd(a,n)=1 gcd(a,n)=1时, a a a才在模 n n n运算中存在乘法逆元,故乘法消去律在该条件下才成立。

2. 素数及其定理

  素数是数论的核心概念,比如著名的哥德巴赫猜想等就与素数有关。素数的定义很简单,与之对应的还有合数的概念:

  • 素数:正因子只有 1 1 1和它本身的正整数称为素数,而且规定 1 1 1不是素数,常记作 p p p
  • 合数:合数是指正整数中不是素数的数,其除 1 1 1和它本身之外,还有其他因子

因此, 2 2 2是最小的素数,除 2 2 2以外,素数都为奇数,最小的合数为 4 4 4。合数有一个非常重要的性质,称为算术基本定理:

  • 算术基本定理:任何合数都可以唯一分解为若干个素数的乘积。

  即对于任何整数 a > 1 a>1 a>1可以唯一分解为 a = p 1 a 1 p 2 a 2 . . . p n a n a=p_1^{a_1} p_2^{a_2}... p_n^{a_n} a=p1a1p2a2...pnan ∀ i ∈ { 1 , 2 , . . . , n } \forall i\in \{1, 2, ..., n\} i{ 1,2,...,n} p i p_i pi是素数( p 1 < p 2 < . . . < p n p_1<p_2<...<p_n p1<p2<...<pn), a i a_i ai是正整数。

  关于素数,有两个常用的定理——费马小定理和欧拉定理,这两个定理在密码学中应用十分广泛。

  • 费马小定理:若 p p p是素数,则对任何与 p p p互素的正整数 a a a有,则有 a p − 1 ≡ 1 ( m o d    p ) a^{p-1}\equiv 1(mod\;p) ap11(modp)

  该定理还有另外一种形式:若 p p p是素数,且 a ∈ Z + a\in Z^+ aZ+,那么 a p ≡ a ( m o d    p ) a^p\equiv a(mod\;p) apa(modp)。因此可以总结费马小定理为:若 p p p是素数,则 ∀ a ∈ Z + \forall a\in Z^+ aZ+ a p ≡ a ( m o d    p ) a^p\equiv a(mod\;p) apa(modp),进一步地,若 a a a p p p互素,则有 a p − 1 ≡ 1 ( m o d    p ) a^{p-1}\equiv 1(mod\;p) ap11(modp)

  • 欧拉定理:对于任意互素的正整数 a a a n n n有: a ϕ ( n ) ≡ 1 ( m o d    n ) a^{\phi(n)}\equiv 1(mod\;n) aϕ(n)1(modn)

  其中 ϕ ( n ) \phi(n) ϕ(n)称为欧拉函数,是指小于等于 n n n的与 n n n互素的正整数个数,常采用下面几个公式计算 ϕ ( n ) \phi(n) ϕ(n)

  • n n n是素数,则 ϕ ( n ) = n − 1 \phi(n)=n-1 ϕ(n)=n1
  • n = p q n=pq n=pq,其中 p p p q q q均为素数,那么 ϕ ( n ) = ϕ ( p ) ϕ ( q ) \phi(n)=\phi(p)\phi(q) ϕ(n)=ϕ(p)ϕ(q),进一步地若 p p p q q q互素( g c d ( p , q ) = 1 gcd(p,q)=1 gcd(p,q)=1),那么 ϕ ( n ) = ϕ ( p ) ϕ ( q ) \phi(n)=\phi(p)\phi(q) ϕ(n)=ϕ(p)ϕ(q)也成立
  • n = p t n=p^t n=pt,其中p是素数,那么 ϕ ( n ) = p t − p t − 1 \phi(n)=p^t-p^{t-1} ϕ(n)=ptpt1

  总结一下,对于费马定理和欧拉定理,如果计算 a x ≡ b ( m o d    n ) a^x\equiv b(mod\;n) axb(modn)中的一些参数,那么如果 n n n是素数,那么考虑费马定理,若 n n n不是素数则考虑欧拉定理。

  最后,介绍一下离散对数问题(Discrete logarithm),离散对数问题是包括Diffie-Hellman密钥交换算法和数字签名算法(DSA)在内的许多公钥算法的基础。在介绍离散对数问题之前,还需要介绍一下本原根的概念,它是离散对数的基础。

  • 本原根:使得 a m ≡ 1 ( m o d    n ) a^m\equiv 1(mod\;n) am1(modn)的最小正整数 m m m称为 a a a的阶,若 m = ϕ ( n ) m=\phi(n) m=ϕ(n) a a a称为 n n n的本原根

  本原根的定义是抽象的,实际上,若考虑 X X X为小于等于 n n n且与 n n n互素的正整数集合,即 X = { x 1 , x 2 , . . . , x ϕ ( n ) } X=\{x_1, x_2, ..., x_{\phi(n)}\} X={ x1,x2,...,xϕ(n)},其中 ∀ i ∈ { 1 , 2 , . . . , ϕ ( n ) } \forall i\in\{1, 2, ..., \phi(n)\} i{ 1,2,...,ϕ(n)} g c d ( x i , n ) = 1 gcd(x_i, n)=1 gcd(xi,n)=1 a a a n n n的本原根当且仅当集合 { ( a 1    m o d    n ) , ( a 2    m o d    n ) , . . . , ( a ϕ ( n )    m o d    n ) } = X \{(a^1\;mod\;n), (a^2\;mod\;n),...,(a^{\phi(n)}\;mod\;n)\}=X { (a1modn),(a2modn),...,(aϕ(n)modn)}=X

  根据定义,对于一个素数 p p p(本原根定义中不要求素数)而言,由于 ϕ ( p ) = p − 1 \phi(p)=p-1 ϕ(p)=p1,且上述定义的集合 X = { 1 , 2 , . . . , p − 1 } X=\{1,2,...,p-1\} X={ 1,2,...,p1},故设 a a a为本原根,则 a a a满足:

{ ( a 1    m o d    p ) , ( a 2    m o d    p ) , . . . , ( a ϕ ( p )    m o d    p ) } = { ( a 1    m o d    p ) , ( a 2    m o d    p ) , . . . , ( a p − 1    m o d    p ) } = { 1 , 2 , . . . , p − 1 } \{(a^1\;mod\;p),(a^2\;mod\;p),...,(a^{\phi (p)}\;mod\;p)\} \\ = \{(a^1\;mod\;p),(a^2\;mod\;p),...,(a^{p-1}\;mod\;p)\} \\ = \{1,2,...,p-1\}\qquad\qquad\qquad\qquad\qquad\qquad { (a1modp),(a2modp),...,(aϕ(p)modp)}={ (a1modp),(a2modp),...,(ap1modp)}={ 1,2,...,p1}

  因此对于任何整数 b b b b    m o d    p ∈ { 1 , 2 , . . . , p − 1 } b\;mod\;p\in \{1,2,...,p-1\} bmodp{ 1,2,...,p1},故一定存在 i ∈ { 1 , 2 , . . . , p − 1 } i\in \{1,2,...,p-1\} i{ 1,2,...,p1}使得 a i ≡ b ( m o d    p ) a^i\equiv b(mod\;p) aib(modp),此时 i i i就被称为以 a a a为底模 p p p运算的 b b b的离散对数,记作 i = d l o g a , p b i=dlog_{a,p}b i=dloga,pb

  • 离散对数:若 a i ≡ b ( m o d    p ) a^i\equiv b(mod\;p) aib(modp),此时 i i i就被称为以 a a a为底模 p p p运算的 b b b的离散对数,记作 i = d l o g a , p b i=dlog_{a,p}b i=dloga,pb

  离散对数是基于本原根的概念,只有存在本原根时才存在唯一的以 a a a为底模 m m m的离散对数,而模数 m m m一般选为素数,因为素数存在本原根。最后介绍一下离散对数难题:

  • 离散对数难题:对于方程 y = g x    m o d    p y=g^x\;mod\;p y=gxmodp,已知 g , x , p g,x,p g,x,p可以很容易计算 y y y,而已知 y , g , p y,g,p y,g,p很难计算 x x x,是指数级别复杂度的,因此计算离散对数是计算困难的。

扩展篇

  相比于基础篇,扩展篇增加了很多内容,尤其是定理的证明,不过对于初学者而言,不需要对此有很深刻的理解,初学时跳过即可。

1. 整数的整除和同余

  数论中主要研究整数的性质,特别是两个整数之间的关系,其中整除和同余是经常被讨论的。

1.1 整除和余数

  在小学里,我们学过这样一个公式:被除数    ÷    \;\div\; ÷除数    =    \;=\; =商…余数。整除的含义即为余数为0 ,而当余数不为0时,此时就需要用余数表示不能整除的部分,下面就从整除出发,介绍整数的整除和余数的基本概念。

1.1.1 带余除法

  尽管整除理解起来很简单,但还是需要给出整除的形式化定义:

  • 整除:设 a , b , m ∈ Z a, b, m\in Z a,b,mZ ∃ m \exists m m使得 a = m b a = mb a=mb成立,则称非零整数 b b b整除 a a a,记作 b ∣ a b|a ba,此时称 b b b a a a的因子, a a a b b b的倍数。

  特殊地,任何不等于 0 0 0的整数都整除 0 0 0,即 ∀ a ≠ 0 , a ∣ 0 \forall a \neq 0, a|0 a=0,a0,而且 1 1 1整除任何整数,即 ∀ a ∈ Z , 1 ∣ a \forall a \in Z, 1|a aZ,1a

  不过大多数时候都可能除不尽,即余数不为 0 0 0,那么就会有余数(remainder)的概念。在数论中,带余除法描述了这一情形,下面是带余除法的形式化定义:

  • 带余除法 ∀ n ∈ Z + \forall n \in Z^+ nZ+ ∀ a ∈ Z \forall a \in Z aZ ∃ q , r ∈ Z \exists q,r \in Z q,rZ 0 ≤ r < n 0\leq r <n 0r<n使得 a = q n + r a=qn+r a=qn+r,其中商 q = ⌊ a / n ⌋ q=\lfloor a/n \rfloor q=a/n ⌊ ⌋ \lfloor \rfloor 为向下取整,而余数 r = a − ⌊ a / n ⌋ × n r=a-\lfloor a/n \rfloor \times n r=aa/n×n

  下面是带余除法的图示表示,可以看到 a a a q q q是同号的,因为需要保证余数是非负整数。

1.1.2 最大公因子

  在整除定义中提到了因子的概念, m ∣ a m|a ma说明 m m m a a a的因子,若 m ∣ a m|a ma m ∣ b m|b mb说明 m m m a , b a,b a,b的因子,称为 a a a b b b的公因子,由于 1 1 1是任何整数的因子,故公因子一定存在(至少为 1 1 1),而关注最多的的是最大的公因子:

  • 最大公因子(Greatest Common Divisor):设 a , b , m ∈ Z a, b, m \in Z a,b,mZ,而且 m ∣ a , m ∣ b m|a, m|b ma,mb,若 m m m是整除 a a a b b b的最大整数,那么 m m m称为 a a a b b b的最大公因子,记作 m = g c d ( a , b ) m = gcd(a, b) m=gcd(a,b)

  一般而言,最大公因子要求是正整数,因为对于 m ∈ Z + m\in Z^+ mZ+,如果 m ∣ a m|a ma,那么 − m ∣ a -m|a ma,显然 − m < m -m<m m<m。同时可以得到对于 a , b ∈ Z + , g c d ( a , b ) = g c d ( a , − b ) = g c d ( − a , b ) = g c d ( − a , − b ) a, b\in Z^+, gcd(a, b) = gcd(a, -b) = gcd(-a, b) = gcd(-a, -b) a,bZ+,gcd(a,b)=gcd(a,b)=gcd(a,b)=gcd(a,b),因此求解最大公因子时 ∀ a , b ∈ Z , g c d ( a , b ) = g c d ( ∣ a ∣ , ∣ b ∣ ) \forall a, b\in Z, gcd(a, b) = gcd(|a|, |b|) a,bZ,gcd(a,b)=gcd(a,b),特殊地有: g c d ( a , 0 ) = ∣ a ∣ gcd(a, 0) = |a| gcd(a,0)=a ∀ a ∈ Z \forall a\in Z aZ g c d ( a , 1 ) = 1 gcd(a, 1) = 1 gcd(a,1)=1

  其中特别要注意 0 0 0的情况,因子是指非零整数,故 0 0 0不是任何整数的因子,但任何非零整数都是 0 0 0的因子,不过为了使得定义有效,规定 g c d ( 0 , 0 ) = 0 gcd(0, 0) = 0 gcd(0,0)=0

互素
  利用最大公因子,可以定义一个常用的概念,即互素:称整数 a , b a,b a,b是互素的,当且仅当 g c d ( a , b ) = 1 gcd(a,b)=1 gcd(a,b)=1

1.1.3 欧几里得算法

  最大公因子是联系两个整数的桥梁之一,因此求解两个整数的最大公因子的算法也尤为重要,下面描述的算法是经典的欧几里得算法(Euclidean Algorithm),直至今日,欧几里得算法仍是计算最大公因子的有效算法,下面是欧几里得算法的基本思想:

  对于任何整数 a a a b b b(由于 g c d ( a , b ) = g c d ( ∣ a ∣ , ∣ b ∣ ) gcd(a, b) = gcd(|a|, |b|) gcd(a,b)=gcd(a,b),这里假定 a > b ≥ 0 a>b\ge 0 a>b0),利用带余除法有 a = q 1 b + r 1 ( 0 < r 1 < b ) a = q_1b + r_1(0<r_1<b) a=q1b+r1(0<r1<b),其中 r 1 ≠ 0 r_1\ne 0 r1=0,否则 g c d ( a , b ) = b gcd(a,b)=b gcd(a,b)=b,下面证明 g c d ( a , b ) = g c d ( b , r 1 ) gcd(a, b) = gcd(b, r_1) gcd(a,b)=gcd(b,r1)

【证】 g c d ( a , b ) = g c d ( b , r 1 ) gcd(a, b) = gcd(b, r_1) gcd(a,b)=gcd(b,r1)
  因为最大公因子一定存在,因此设 d = g c d ( a , b ) , g = g c d ( b , r 1 ) d=gcd(a, b), g = gcd(b, r1) d=gcd(a,b),g=gcd(b,r1),则 d ∣ a ,    d ∣ b ,    g ∣ b ,    g ∣ r 1 d|a, \;d|b, \;g|b, \;g|r_1 da,db,gb,gr1,根据带余除法有 a = q 1 b + r 1 a = q_1b + r_1 a=q1b+r1,那么就有下面的证明:
  对 a = q 1 b + r 1 a = q_1b + r_1 a=q1b+r1两边同除以 d d d有: a / d = q 1 b / d + r 1 / d a/d = q_1b/d + r_1/d a/d=q1b/d+r1/d,则 r 1 / d r_1/d r1/d必须是整数,故 d d d也是 b b b r 1 r_1 r1的因子,则 d d d也是 b b b r 1 r_1 r1的公因子,根据定义 g g g是最大的公因子,因此有 d ≤ g d \le g dg
  同理对 a = q 1 b + r 1 a = q_1b + r_1 a=q1b+r1两边同除以 g g g有: a / g = q 1 b / g + r 1 / g a/g = q_1b/g + r_1/g a/g=q1b/g+r1/g,故 g g g a a a b b b的因子,根据定义 g ≤ d g \le d gd
  综上 d = g d=g d=g

  因此多次使用带余除法有:
a = q 1 b + r 1      ( 0 < r 1 < b ) b = q 2 r 1 + r 2 ( 0 < r 2 < r 1 ) r 1 = q 3 r 2 + r 3 ( 0 < r 3 < r 2 ) . . . r n − 2 = q n r n − 1 + r n ( 0 < r n < r n − 1 ) r n − 1 = q n + 1 r n + 0 ⇒ g c d ( a , b ) = r n a = q_1b + r_1\qquad\;\;(0<r_1<b)\\ b = q_2r_1 + r_2\qquad(0<r_2<r_1)\\ r_1 = q_3r_2 + r_3\qquad(0<r_3<r_2)\\ ...\\ r_{n-2} = q_nr_{n-1} + r_n\quad(0<r_n<r_{n-1})\\ r_{n-1}=q_{n+1}r_n+0\quad \Rightarrow gcd(a,b)=r_n\\ a=q1b+r1(0<r1<b)b=q2r1+r2(0<r2<r1)r1=q3r2+r3(0<r3<r2)...rn2=qnrn1+rn(0<rn<rn1)rn1=qn+1rn+0gcd(a,b)=rn

  根据 0 ≤ r n < r n − 1 < . . . < r 3 < r 2 < r 1 < b 0\le r_n<r_{n-1}<...<r_3<r_2<r_1<b 0rn<rn1<...<r3<r2<r1<b,且 b b b是有界,故 ∃ n \exists n n,使得 r n − 1 = q n + 1 r n + 0 r_{n-1}=q_{n+1}r_n+0 rn1=qn+1rn+0(即余数一定会减小至 0 0 0),此时根据上述有 g c d ( a , b ) = g c d ( b , r 1 ) = g c d ( r n − 1 , r n ) = g c d ( r n , 0 ) = r n gcd(a,b) = gcd(b,r_1)=gcd(r_{n-1},r_n)=gcd(r_n,0)=r_n gcd(a,b)=gcd(b,r1)=gcd(rn1,rn)=gcd(rn,0)=rn。下面是欧几里得算法的实现:

# 利用Euclid算法计算最小公因数gcd(a, b)
def Euclid_gcd(a, b):
    r1 = max(abs(a), abs(b))     # 令r1等于绝对值大的数
    r2 = min(abs(a), abs(b))     # 令r2等于绝对值小的数
    if r2 == 0:
        return r1
    else:
        return Euclid_gcd(r2, r1%r2)     # %是模运算符号,下面会讲到

  欧几里得算法即使对于很大的整数都十分有效,可以证明对于 1 ≤ m , n ≤ 2 N 1\le m, n\le 2^N 1m,n2N,计算 g c d ( m , n ) gcd(m,n) gcd(m,n)至多需要 2 N 2N 2N次迭代的计算,看看下面的例子:

gcd(1160718174, 316258250)
= gcd(316258250, 211943424)
= gcd(211943424, 104314826)
= ...
= gcd(1078, 0)
= 1078

1.1.4 扩展的欧几里得算法

  为了方便之后的讲述,下面还需要介绍一个定理:

  • 定理 ∀ a , b ∈ Z ,    ∃ x , y ∈ Z \forall a,b\in Z,\;\exist x,y\in Z a,bZ,x,yZ使得 x a + y b = g c d ( a , b ) xa + yb = gcd(a,b) xa+yb=gcd(a,b)

  定理的证明不是重点,求解 u u u v v v才是重要的,下面就对 u u u v v v的值进行推导:假设在下面的每一个步骤可以找到 x i x_i xi y i y_i yi使得 r i = a x i + b y i r_i=ax_i+by_i ri=axi+byi

带余除法 假设
a = q 1 b + r 1 a = q_1b + r_1 a=q1b+r1 r 1 = a x 1 + b y 1 r_1=ax_1+by_1 r1=ax1+by1
b = q 2 r 1 + r 2 b = q_2r_1 + r_2 b=q2r1+r2 r 2 = a x 2 + b y 2 r_2=ax_2+by_2 r2=ax2+by2
r 1 = q 3 r 2 + r 3 r_1 = q_3r_2 + r_3 r1=q3r2+r3 r 3 = a x 3 + b y 3 r_3=ax_3+by_3 r3=ax3+by3
. . . ... ...
r n − 2 = q n r n − 1 + r n r_{n-2} = q_nr_{n-1} + r_n rn2=qnrn1+rn r n = a x n + b y n r_n=ax_n+by_n rn=axn+byn
r n − 1 = q n + 1 r n + 0 r_{n-1}=q_{n+1}r_n+0 rn1=qn+1rn+0

  因此有 r i = r i − 2 − q i r i − 1 r_i = r_{i-2} - q_ir_{i-1} ri=ri2qiri1,而 r i − 1 = a x i − 1 + b y i − 1 r_{i-1}=ax_{i-1}+by_{i-1} ri1=axi1+byi1 r i − 2 = a x i − 2 + b y i − 2 r_{i-2}=ax_{i-2}+by_{i-2} ri2=axi2+byi2

  故 r i = ( a x i − 2 + b y i − 2 ) − q i ( a x i − 1 + b y i − 1 ) = a ( x i − 2 − q i x i − 1 ) + b ( y i − 2 − q i y i − 1 ) r_i = (ax_{i-2}+by_{i-2}) - q_i(ax_{i-1}+by_{i-1}) = a(x_{i-2}-q_ix_{i-1})+b(y_{i-2}-q_iy_{i-1}) ri=(axi2+byi2)qi(axi1+byi1)=a(xi2qixi1)+b(yi2qiyi1)

  再根据 r i = a x i + b y i r_i=ax_i+by_i ri=axi+byi有: x i = x i − 2 − q i x i − 1 , y i = y i − 2 − q i y i − 1 x_i=x_{i-2}-q_ix_{i-1},\quad y_i=y_{i-2}-q_iy_{i-1} xi=xi2qixi1,yi=yi2qiyi1

  而我们知道 r n = g c d ( a , b ) r_n=gcd(a, b) rn=gcd(a,b),因此 x = x n ,    y = y n x=x_n,\;y=y_n x=xn,y=yn,以上就用扩展欧几里得算法求解 x a + y b = g c d ( a , b ) xa + yb = gcd(a,b) xa+yb=gcd(a,b)的过程,下面就是计算过程:

  其中令 r − 1 = a , r 0 = b r_{-1}=a, r_0=b r1=a,r0=b,而同样有 r i = a x i + b y i r_i=ax_i+by_i ri=axi+byi,不过此时的 x − 1 = 1 , x 0 = 0 x_{-1}=1, x_0=0 x1=1,x0=0 y − 1 = 0 , y 0 = 0 y_{-1}=0, y_0=0 y1=0,y0=0

  下面就是扩展欧几里得算法实现:

# 用扩展的Eculid算法计算ax+by=gcd(a,b)
def Extend_eculid(a, b):
    (r1, r2) = (a, b)
    (x1, x2, y1, y2) = (1, 0, 0, 1)
    while r2 != 0:
        r = r1 % r2
        q = r1 // r2
        (r1, r2) = (r2, r)
        (x1, x2) = (x2, x1 - q*x2)
        (y1, y2) = (y2, y1 - q*y2)
    return(r1, x1, y1)

# 主函数
(a, b) = eval(input("Enter two numbers:"))
a_temp = a if abs(a) > abs(b) else b         # 令a_temp为绝对值较大者
b_temp = b if abs(a) > abs(b) else a         # 令b_temp为绝对值较小者
(g, x, y) = Extend_eculid(a_temp, b_temp)
print("gcd({}, {}) = {} = ({}) * {} + ({}) * {}".format(a_temp, b_temp, g, x, a_temp, y, b_temp))

1.2 同余

1.2.1 同余关系

  尽管整除是一种很好的性质,但不是所有整数都具备,大部分情况而言,对于两个整数相除还是会存在余数,回顾带余除法有:

  • 带余除法 ∀ n ∈ Z + \forall n \in Z^+ nZ+ ∀ a ∈ Z \forall a \in Z aZ ∃ q , r ∈ Z \exists q,r \in Z q,rZ 0 ≤ r < n 0\leq r <n 0r<n使得 a = q n + r a=qn+r a=qn+r,其中 q = ⌊ a / n ⌋ q=\lfloor a/n \rfloor q=a/n ⌊ ⌋ \lfloor \rfloor 为向下取整。

  在这里,我们称 r r r为余数,之前计算r时,有 r = a − ⌊ a / n ⌋ × n r=a-\lfloor a/n \rfloor \times n r=aa/n×n,在这里用一个更加简洁的符号表达 r r r,那就是模运算符号 m o d mod mod,记作 r = a    m o d    n r=a\;mod\;n r=amodn,这里称 n n n是模数,该运算称为模 n n n运算。关于模 n n n运算,它是数论中十分重要的一种运算,下面还会详细定义和讨论该运算。

  注意到一种情况,两个不同的数 a , b a,b a,b都是除以另一个数 n n n可能获得相同的余数,这种情况称为关于模 n n n是同余的:

  • n n n同余:若 a    m o d    n = b    m o d    n a\;mod\;n=b\;mod\;n amodn=bmodn,那么称整数 a a a b b b是模 n n n同余的,记作 a ≡ b ( m o d    n ) a\equiv b(mod\;n) ab(modn).

  同余有一个等价的定义(即充要条件):若 a a a b b b是关于模 n n n同余的,那么 n ∣ ( a − b ) n|(a-b) n(ab),可见同余和整除联系密切。不过同余相比于整除是一个更好的性质,下面比较两种情况:

性质 整除 同余
自反性 ∀ a ≠ 0 ,    a ∥ a \forall a\ne 0,\;a\|a a=0,aa a ≡ a ( m o d    n ) a\equiv a(mod\;n) aa(modn)
对称性 不具备 a ≡ b ( m o d    n ) a\equiv b(mod\;n) ab(modn),则 b ≡ a ( m o d    n ) b\equiv a(mod\;n) ba(modn)
传递性 a ∥ b , b ∥ c ⇒ a ∥ c a\|b, b\|c \Rightarrow a\|c ab,bcac a ≡ b ( m o d    n ) , b ≡ c ( m o d    n ) a\equiv b(mod\;n), b\equiv c(mod\;n) ab(modn),bc(modn) ⇒ a ≡ c ( m o d    n ) \Rightarrow a\equiv c(mod\;n) ac(modn)

  由于同余运算具有自反性、对称性和传递性,因此同余关系是等价关系,所以可以通过同余关系对于集合进行划分,数论主要研究整数集合,因此通过同余关系可以将无穷的整数集合划分为有限的集合,而划分后得到的即为剩余类集。

等价关系
  若定义在集合X上的一种关系(这里可以理解为一种运算,不妨用 R R R表示)具有以下性质:

  • 自反性: ∀ x ∈ X , x R x \forall x\in X, xRx xX,xRx
  • 对称性:若 x R y xRy xRy,则 y R x yRx yRx
  • 传递性:若 x R y , y R z xRy,yRz xRy,yRz,则 x R z xRz xRz

  比如全等三角形中的全等关系就是一种等价关系,不过在这里,不必对于等价关系进行很深的理解,只需明白由全等关系就可以将集合进行划分成若干个部分即可。

1.2.2 剩余类集

  对于任一整数(用 a a a表示),那么利用模运算有 0 ≤ a    m o d    n < n 0\leq a\;mod\;n<n 0amodn<n,因此 a    m o d    n ∈ { 0 , 1 , 2 , . . , n − 1 } a\;mod\;n \in \{0, 1, 2,.., n-1\} amodn{ 0,1,2,..,n1},可以证明 { a    m o d    n ∣ ∀ a ∈ Z } = { 0 , 1 , 2 , . . , n − 1 } \{a\;mod\;n|\forall a\in Z\}=\{0, 1, 2,.., n-1\} { amodnaZ}={ 0,1,2,..,n1},即通过模 n n n运算可以得到 0 ∼ n − 1 0\sim n-1 0n1内的任何一个数,且只能得到其中的一个数。因此我们把余数的集合称为剩余类集,而剩余类集中的数作为剩余类的代表,即有:

  • 剩余类集:模 n n n运算的所有余数的集合,记作 Z n = { 0 , 1 , 2 , . . . , n − 1 } Z_n=\{0, 1, 2,..., n-1\} Zn={ 0,1,2,...,n1}
  • 剩余类:所有模 n n n同余的整数的集合,一般用最小的非负整数作为代表,记作 [ 0 ] , [ 1 ] , [ 2 ] , . . , [ n − 1 ] [0],[1],[2],..,[n-1] [0],[1],[2],..,[n1],对于 [ r ] [r] [r]而言有: [ r ] = { a ∣ a ∈ Z , a ≡ r ( m o d    n ) } [r]=\{a|a \in Z, a\equiv r(mod\;n)\} [r]={ aaZ,ar(modn)}

  下面举一个例子来说明:计算 a    m o d    3 a\;mod\;3 amod3
. . . , − 9 , − 6 , − 3 , 0 , 3 , 6 , 9 , . . .    m o d    3 = 0 . . . , − 8 , − 5 , − 2 , 1 , 4 , 7 , 10 , . . .    m o d    3 = 1 . . . , − 7 , − 4 , − 1 , 2 , 5 , 8 , 11 , . . .    m o d    3 = 2 ..., -9, -6, -3, 0, 3, 6, 9, ...\;mod\;3=0\\ ..., -8, -5, -2, 1, 4, 7, 10, ...\;mod\;3=1\\ ..., -7, -4, -1, 2, 5, 8, 11, ...\;mod\;3=2\\ ...,9,6,3,0,3,6,9,...mod3=0...,8,5,2,1,4,7,10,...mod3=1...,7,4,1,2,5,8,11,...mod3=2

  则 Z 3 = { 0 , 1 , 2 } Z_3=\{0, 1, 2\} Z3={ 0,1,2},而剩余类有 3 3 3个,分别是:

[ 0 ] = { . . . , − 9 , − 6 , − 3 , 0 , 3 , 6 , 9 , . . . } [ 1 ] = { . . . , − 8 , − 5 , − 2 , 1 , 4 , 7 , 10 , . . . } [ 2 ] = { . . . , − 7 , − 4 , − 1 , 2 , 5 , 8 , 11 , . . . } [0]=\{..., -9, -6, -3, 0, 3, 6, 9, ...\}\\ [1]=\{..., -8, -5, -2, 1, 4, 7, 10, ...\}\\ [2]=\{..., -7, -4, -1, 2, 5, 8, 11, ...\}\\ [0]={ ...,9,6,3,0,3,6,9,...}[1]={ ...,8,5,2,1,4,7,10,...}[2]={ ...,7,4,1,2,5,8,11,...}

  在剩余类 [ r ] [r] [r]中有这样的一个性质,他们模 n n n是同余的,在这一点上,剩余类 [ r ] [r] [r]中任何一个元素就可以代表其他元素了,因此就只需要研究这一个元素的性质,就可以大致了解所有元素的共性了,这也是剩余类的本质特性。

1.2.3 模运算

  之所以大费周章地定义剩余类集,是因为可以通过模运算来将所有整数的运算限制在剩余类集中,首先需要正式地定义模运算(Modular arithmetic):

  • n n n运算:称二元运算 a    m o d    n = r a\;mod\;n=r amodn=r是模 n n n运算, r r r a a a n n n的值,且 0 ≤ r < n 0\leq r <n 0r<n

  对于一种运算而言,其最重要的就是运算律,下面就阐述一下模 n n n运算的运算律,并着重讨论其交换律和消去律。

  我们知道对于任意两个整数 a a a b b b a a a b b b的加、减、乘运算之后的结果还是整数(显然除法不是如此),那么 a    m o d    n a\;mod\;n amodn b    m o d    n b\;mod\;n bmodn在剩余类集 Z n Z_n Zn中,而 a ⋅ b    m o d    n a\cdot b\;mod\;n abmodn ⋅ \cdot 代表加、减乘、运算)显然也在剩余类集 Z n Z_n Zn中(只要是整数,模 n n n运算之后就会在剩余类集 Z n Z_n Zn中),那么两者的关系是关注的重点。通过上面的叙述,显然有下面的结论,其证明都可以用带余除法来证明:

  • [ ( a    m o d    n ) + ( b    m o d    n ) ]    m o d    n = ( a + b )    m o d    n [(a\;mod\;n)+(b\;mod\;n)]\;mod\;n=(a+b)\;mod\;n [(amodn)+(bmodn)]modn=(a+b)modn
  • [ ( a    m o d    n ) − ( b    m o d    n ) ]    m o d    n = ( a − b )    m o d    n [(a\;mod\;n)-(b\;mod\;n)]\;mod\;n=(a-b)\;mod\;n [(amodn)(bmodn)]modn=(ab)modn
  • [ ( a    m o d    n ) × ( b    m o d    n ) ]    m o d    n = ( a × b )    m o d    n [(a\;mod\;n)\times (b\;mod\;n)]\;mod\;n=(a\times b)\;mod\;n [(amodn)×(bmodn)]modn=(a×b)modn

  除了加、减、乘运算,模运算是否具有普通运算的运算律呢?这里讨论简单的交换律和消去律,这两种规律是之后计算的基础。先考虑下面的例子,我们进行模 8 8 8的运算有:

  第一栏和第二栏是加法和乘法(减法和加法类似),最右一栏是加法逆元和乘法逆元,它们是消去律的基础,其定义如下:

  • 加法逆元 a , b ∈ Z n a,b\in Z_n a,bZn,若 ( a + b )    m o d    n = 0 (a+b)\;mod\;n=0 (a+b)modn=0,则 a a a b b b互为加法逆元,记 a a a的加法逆元为 − a -a a
  • 乘法逆元 a , b ∈ Z n a,b\in Z_n a,bZn,若 ( a × b )    m o d    n = 1 (a\times b)\;mod\;n=1 (a×b)modn=1,则 a a a b b b互为乘法逆元,记 a a a的乘法逆元为 a − 1 a^{-1} a1

  观察上面的表格,可以得出以下的结论:

  • 关于加法:表格是关于对角线对称的,因此模 n n n加法具有交换律,即 ( a + b )    m o d    n = ( b + a )    m o d    n (a+b)\;mod\;n=(b+a)\;mod\;n (a+b)modn=(b+a)modn
  • 关于乘法:表格是关于对角线对称的,因此模 n n n乘法具有交换律,即 ( a × b )    m o d    n = ( b × a )    m o d    n (a\times b)\;mod\;n=(b\times a)\;mod\;n (a×b)modn=(b×a)modn
  • 关于逆元:加法逆元一定存在,但乘法逆元不一定存在

  关注一下减法,对于减法运算 ( a − b )    m o d    n (a-b)\;mod\;n (ab)modn而言,可以看成是 ( a + ( − b ) )    m o d    n (a+(-b))\;mod\;n (a+(b))modn,其中 − b -b b b b b的加法逆元。不过像普通算术的减法一样,减法不具有交换律。关于运算的其他运算律,如结合律、分配律等同样可以进行分析。

  讨论完交换律和逆元,下面基于逆元来讨论加法和乘法的消去律:在普通的算术运算中有消去律: a + b = a + c ⇒ b = c a+b=a+c\Rightarrow b=c a+b=a+cb=c,和 ∀ a ≠ 0 , a × b = a × c ⇒ b = c \forall a\neq 0, a\times b=a\times c\Rightarrow b=c a=0,a×b=a×cb=c,即在等式两边可以同时消去相同的数,那么在模运算上有下面的证明:

  由于加法逆元存在,则有

( a + b )    m o d    n = ( a + c )    m o d    n ⇒ ( a + b ) ≡ ( a + c ) ( m o d    n ) ⇒ ( ( − a ) + a + b ) ≡ ( ( − a ) + a + c ) ( m o d    n ) ⇒ b ≡ c ( m o d    n ) (a+b)\;mod\;n=(a+c)\;mod\;n\Rightarrow (a+b)\equiv (a+c)(mod\;n)\Rightarrow ((-a)+a+b)\equiv ((-a)+a+c)(mod\;n)\Rightarrow b\equiv c(mod\;n) (a+b)modn=(a+c)modn(a+b)(a+c)(modn)((a)+a+b)((a)+a+c)(modn)bc(modn)

  而乘法逆元不一定存在,因此下式只对于乘法逆元存在的情况:

( a × b )    m o d    n = ( a × c )    m o d    n ⇒ ( a × b ) ≡ ( a × c ) ( m o d    n ) ⇒ ( ( a − 1 ) × a × b ) ≡ ( ( a − 1 ) × a × c ) ( m o d    n ) ⇒ b ≡ c ( m o d    n ) (a\times b)\;mod\;n=(a\times c)\;mod\;n\Rightarrow (a\times b)\equiv (a\times c)(mod\;n)\Rightarrow ((a^{-1})\times a\times b)\equiv ((a^{-1})\times a\times c)(mod\;n)\Rightarrow b\equiv c(mod\;n) (a×b)modn=(a×c)modn(a×b)(a×c)(modn)((a1)×a×b)((a1)×a×c)(modn)bc(modn)

模运算与普通运算
  模运算是一种新定义的运算,我们所熟知的规律不一定在该运算下成立,因此对于任何证明也都应保持这种敏锐感,对于上面的证明,利用了一个假设:在模运算的等式两边同乘任何数,等式仍然成立。这个假设在普通运算下是毫无疑问的,但在模运算下仍然需要引起怀疑,不过这个假设是正确的。如证明 a ≡ b ( m o d    n ) ⇒ a c ≡ b c ( m o d    n ) a\equiv b(mod\;n)\Rightarrow ac\equiv bc(mod \;n) ab(modn)acbc(modn),利用带余除法 a = q 1 n + r , b = q 2 n + r a=q_1n+r,b=q_2n+r a=q1n+r,b=q2n+r展开等式便可证明。

  因此判断乘法逆元是否存在也变得十分关键,对于模 n n n运算而言, a a a的乘法逆元存在的充要条件为 a a a n n n互素,即 g c d ( a , n ) = 1 gcd(a,n)=1 gcd(a,n)=1,下面用一个例子来说明原因:

Z 8 Z_8 Z8 0 1 2 3 4 5 6 7
a = 6 a=6 a=6乘以 Z 8 Z_8 Z8中各元素行模 8 8 8运算
∀ b ∈ Z 8 ( b × 6 ) ( m o d    8 ) \forall b\in Z_8\quad(b \times 6)(mod\;8) bZ8(b×6)(mod8) 0 6 4 2 0 6 4 2
a = 5 a=5 a=5乘以 Z 8 Z_8 Z8中各元素进行模 8 8 8运算
∀ b ∈ Z 8 ( b × 5 ) ( m o d    8 ) \forall b\in Z_8\quad(b \times 5)(mod\;8) bZ8(b×5)(mod8) 0 5 2 7 4 1 6 3

  记 { ( b × a ) ( m o d    n ) ∣ ∀ b ∈ Z n } \{(b \times a)(mod\;n)|\forall b\in Z_n\} { (b×a)(modn)bZn}为用 a a a乘以 Z n Z_n Zn中所有元素所产生的集合,我们看到当 a a a n n n不互素时,集合 { ( b × a ) ( m o d    n ) ∣ ∀ b ∈ Z n } ⊂ Z 8 \{(b \times a)(mod\;n)|\forall b\in Z_n\}\sub Z_8 { (b×a)(modn)bZn}Z8,而当 a a a n n n互素时 { ( b × a ) ( m o d    n ) ∣ ∀ b ∈ Z n } = Z 8 \{(b \times a)(mod\;n)|\forall b\in Z_n\}=Z_8 { (b×a)(modn)bZn}=Z8。因此当 a a a n n n不互素时,集合 Z 8 Z_8 Z8到集合 { ( b × a ) ( m o d    n ) ∣ ∀ b ∈ Z n } \{(b \times a)(mod\;n)|\forall b\in Z_n\} { (b×a)(modn)bZn}的映射是多对一的映射,而当 a a a n n n互素是一对一的映射,求逆元的元素相当于逆映射,只有一对一的映射(一一映射)才有逆映射,此时才有逆元。

  因此总结一下关于模运算的规律:

  • [ ( a    m o d    n ) + ( b    m o d    n ) ]    m o d    n = ( a + b )    m o d    n [(a\;mod\;n)+(b\;mod\;n)]\;mod\;n=(a+b)\;mod\;n [(amodn)+(bmodn)]modn=(a+b)modn
  • [ ( a    m o d    n ) − ( b    m o d    n ) ]    m o d    n = ( a − b )    m o d    n [(a\;mod\;n)-(b\;mod\;n)]\;mod\;n=(a-b)\;mod\;n [(amodn)(bmodn)]modn=(ab)modn
  • [ ( a    m o d    n ) × ( b    m o d    n ) ]    m o d    n = ( a × b )    m o d    n [(a\;mod\;n)\times (b\;mod\;n)]\;mod\;n=(a\times b)\;mod\;n [(amodn)×(bmodn)]modn=(a×b)modn
  • 加法交换律 ( a + b )    m o d    n = ( b + a )    m o d    n (a+b)\;mod\;n=(b+a)\;mod\;n (a+b)modn=(b+a)modn
  • 乘法交换律 ( a × b )    m o d    n = ( b × a )    m o d    n (a\times b)\;mod\;n=(b\times a)\;mod\;n (a×b)modn=(b×a)modn
  • 加法消去律 a + b = a + c ⇒ b = c    ( m o d    n ) a+b=a+c\Rightarrow b=c\;(mod\;n) a+b=a+cb=c(modn)
  • 乘法消去律 g c d ( a , n ) = 1 gcd(a,n)=1 gcd(a,n)=1): ∀ a ≠ 0 , a × b = a × c ⇒ b = c    ( m o d    n ) \forall a\neq 0, a\times b=a\times c\Rightarrow b=c\;(mod\;n) a=0,a×b=a×cb=c(modn)

2. 素数

  下面开始数论的核心——素数,比如著名的哥德巴赫猜想等就与素数有关,下面将介绍素数的基本概念,讨论与素数的定理和应用。

2.1 素数及其定理

  素数的定义十分简单,与素数相对的即为合数,两者的定义如下:

  • 素数:整数 p > 1 p>1 p>1是素数,当且仅当 p p p的正因子只有 1 1 1 p p p
  • 合数:合数是指正整数中不是素数的数,其除 1 1 1和它本身之外,还有其他因子

  合数有一个十分重要的性质,也称为算术基本定理:

  • 算术基本定理:任何合数都可以唯一分解为若干个素数的乘积。

  因此,对于任何整数 a > 1 a>1 a>1可以唯一分解为 a = p 1 a 1 p 2 a 2 . . . p n a n a=p_1^{a_1} p_2^{a_2}... p_n^{a_n} a=p1a1p2a2...pnan ∀ i ∈ { 1 , 2 , . . . , n } \forall i\in \{1, 2, ..., n\} i{ 1,2,...,n} p i p_i pi是素数( p 1 < p 2 < . . . < p n p_1<p_2<...<p_n p1<p2<...<pn), a i a_i ai是正整数。

  例如 30 = 2 × 3 × 5 30 = 2\times 3\times 5 30=2×3×5,不过对一个数进行素因子分解是困难的,特别是对大整数。基于素数,有下面两个定理——费马小定理和欧拉定理,它们在公钥密码学上有非常重要的应用。

2.1.1 费马小定理

  • 费马小定理(Fermat’s little theorem):若 p p p是素数,则对任何与 p p p互素的正整数 a a a有,则有 a p − 1 ≡ 1 ( m o d    p ) a^{p-1}\equiv 1(mod\;p) ap11(modp)

  正如前述, a a a p p p互素说明 g c d ( a , p ) = 1 gcd(a,p)=1 gcd(a,p)=1,不过由于 p p p是素数,因此其还有以下两层含义:

  • a a a不是 p p p的倍数,即 a ≠ p , 2 p , . . . a\ne p, 2p, ... a=p,2p,...,即只有素数的倍数才不与素数互素
  • a a a Z p Z_p Zp中有乘法逆元

【证】 a p − 1 ≡ 1 ( m o d    p ) a^{p-1}\equiv 1(mod\;p) ap11(modp)

  令 Z p + = { 1 , 2 , . . . , p − 1 } ,    X = { ( a    m o d    p ) , ( 2 a    m o d    p ) , ( 3 a    m o d    p ) , . . . , ( ( p − 1 ) a    m o d    p ) } Z_p^+=\{1,2,...,p-1\},\;X=\{(a\;mod\;p),(2a\;mod\;p),(3a\;mod\;p),...,((p-1)a\;mod\;p)\} Zp+={ 1,2,...,p1},X={ (amodp),(2amodp),(3amodp),...,((p1)amodp)}

  显然 ∀ i ≠ j ∈ { 1 , 2 , 3 , . . . p − 1 } \forall i\ne j\in \{1,2,3,...p-1\} i=j{ 1,2,3,...p1} ( i a    m o d    p ) ≠ ( j a    m o d    p ) (ia\;mod\;p)\ne (ja\;mod\;p) (iamodp)=(jamodp),否则两边同乘 a − 1 a^{-1} a1 a a a p p p互素)便可得到 ( i    m o d    p ) = ( j    m o d    p ) (i\;mod\;p)= (j\;mod\;p) (imodp)=(jmodp),从而得到 i = j i=j i=j,故 X X X中没有重复元素。

  因此 X X X中有 p − 1 p-1 p1个元素,且每个元素都在 { 1 , 2 , 3 , . . . , p − 1 } \{1,2,3,...,p-1\} { 1,2,3,...,p1}中,故 Z p + = X Z_p^+=X Zp+=X,故有下面的等式:

1 × 2 × 3 × . . . × ( p − 1 ) = ( a    m o d    p ) × ( 2 a    m o d    p ) × ( 3 a    m o d    p ) × . . . × ( ( p − 1 ) a    m o d    p 1\times 2\times 3\times ...\times (p-1)=(a\;mod\;p)\times (2a\;mod\;p)\times (3a\;mod\;p)\times ...\times ((p-1)a\;mod\;p 1×2×3×...×(p1)=(amodp)×(2amodp)×(3amodp)×...×((p1)amodp

  整理得 ( p − 1 ) ! = ( p − 1 ) ! × a p ( m o d    p ) ⇒ a p − 1 ≡ 1 ( m o d    p ) (p-1)!=(p-1)!\times a^p (mod\;p)\Rightarrow a^{p-1}\equiv 1(mod\;p) (p1)!=(p1)!×ap(modp)ap11(modp)(注意 ( p − 1 ) ! (p-1)! (p1)! p p p互素)

  事实上,费马小定理还有另一种形式:

  • 费马小定理另一形式:若 p p p是素数,且 a ∈ Z + a\in Z^+ aZ+,那么 a p ≡ a ( m o d    p ) a^p\equiv a(mod\;p) apa(modp)

  该形式可用数学归纳法证明,或者基于上述 a p − 1 ≡ 1 ( m o d    p ) a^{p-1}\equiv 1(mod\;p) ap11(modp)进行证明,下面是证明要点:

【证】 a p ≡ a ( m o d    p ) a^p\equiv a(mod\;p) apa(modp)

  若 a a a p p p互素,那么有 a p − 1 ≡ 1 ( m o d    p ) a^{p-1}\equiv 1(mod\;p) ap11(modp),两边同乘a可得 a p ≡ a ( m o d    p ) a^p\equiv a(mod\;p) apa(modp),若 a a a p p p不互素,那么有 a = n p ( n = 1 , 2 , 3 , . . . . ) a=np(n=1, 2, 3,....) a=np(n=1,2,3,....),则 a p ( m o d    p ) = ( n p ) p ( m o d    p ) = 0 = n p ( m o d    p ) = a ( m o d    p ) a^p(mod\;p)=(np)^p(mod\;p)=0=np(mod\;p)=a(mod\;p) ap(modp)=(np)p(modp)=0=np(modp)=a(modp)

  事实上,第一种形式是第二种形式的特殊情况,在第二种形式 a p ≡ a ( m o d    p ) a^p\equiv a(mod\;p) apa(modp)中,由于 a a a p p p互素,则可以在两边乘以 a − 1 a^{-1} a1,便可得到 a p − 1 ≡ 1 ( m o d    p ) a^{p-1}\equiv 1(mod\;p) ap11(modp)。因此可以总结费马小定理为:

  • 费马小定理:若 p p p是素数,则 ∀ a ∈ Z + \forall a\in Z^+ aZ+ a p ≡ a ( m o d    p ) a^p\equiv a(mod\;p) apa(modp),进一步地,若 a a a p p p互素,则有 a p − 1 ≡ 1 ( m o d    p ) a^{p-1}\equiv 1(mod\;p) ap11(modp)

2.1.2 欧拉定理

  在讲述欧拉定理(Euler’s theorem)之前要先介绍欧拉函数(Euler’s totient function),其定义如下:

  • 欧拉函数:正整数 n n n的欧拉函数是指小于等于 n n n的与 n n n互素的正整数个数,记作 ϕ ( n ) \phi(n) ϕ(n)

  计算 ϕ ( n ) \phi(n) ϕ(n)是十分重要的,在之后的练习中常常用到,下面介绍几个公式:

  • n n n是素数,则 ϕ ( n ) = n − 1 \phi(n)=n-1 ϕ(n)=n1
  • n = p q n=pq n=pq,其中 p p p q q q均为素数,那么 ϕ ( n ) = ϕ ( p ) ϕ ( q ) \phi(n)=\phi(p)\phi(q) ϕ(n)=ϕ(p)ϕ(q),进一步地若 p p p q q q互素,那么 ϕ ( n ) = ϕ ( p ) ϕ ( q ) \phi(n)=\phi(p)\phi(q) ϕ(n)=ϕ(p)ϕ(q)也成立
  • n = p t n=p^t n=pt,其中p是素数,那么 ϕ ( n ) = p t − p t − 1 \phi(n)=p^t-p^{t-1} ϕ(n)=ptpt1

  上面第一点和第三点按照定义即可证明,对其因子计数即可。而对于第二点,对于前半部分 p p p q q q是素数的情况,可以列举 p p p q q q的因子并按照定义加以证明,而 p p p q q q互素的情况则需要利用中国剩余定理(之后会讲述)证明,这里忽略公式的证明,能够熟练地记住和利用公式便可。

  下面介绍计算 ϕ ( n ) \phi(n) ϕ(n)的步骤:

  1. ϕ ( 1 ) = 1 \phi(1)=1 ϕ(1)=1
  2. n n n是素数,则 ϕ ( n ) = n − 1 \phi(n)=n-1 ϕ(n)=n1
  3. n n n不是素数,则由算术基本定理可知: n n n可表示为 n = p 1 n 1 p 2 n 2 p 3 n 3 . . . p t n t n=p_1^{n_1} p_2^{n_2} p_3^{n_3}... p_t^{n_t} n=p1n1p2n2p3n3...ptnt,其中 ∀ i ∈ { 1 , 2 , 3 , . . . , n } \forall i\in \{1, 2, 3, ..., n\} i{ 1,2,3,...,n} p i p_i pi是素数( p 1 < p 2 < p 3 < . . . < p t p_1<p_2<p_3<...<p_t p1<p2<p3<...<pt), n i n_i ni是正整数,则利用上面的三个欧拉函数的计算公式可以推出: ϕ ( n ) = ∏ i = 1 t p i n i − 1 ( p i − 1 ) \phi(n)=\prod_{i=1}^t{p_{i}^{n_i-1}( p_i-1 )} ϕ(n)=i=1tpini1(pi1)

  下面是计算欧拉函数的算法实现

import math
# 判断素数函数
def isprime(n):
    if n < 2:
        return False
    for i in range(2, int(math.sqrt(n))+1):
        if n % i == 0:
            return False
    return True

# 求欧拉函数phi(n)
def phi(n):
    assert n > 0
    if n == 1:        # n = 1
        return 1
    elif isprime(n):  # n是素数
        return n-1
    else:             # n不是素数
        factor_dict = {
    
    }     # 对n进行素因子分解
        while n != 1:
            for i in range(2, n+1):
                if n%i==0 and isprime(i):   # i是n的素因子
                    factor_dict[i] = factor_dict.get(i, 0) + 1
                    n = n // i
                    break
        phi = 1              # 计算欧拉函数的值
        for key in factor_dict.keys():
            value = factor_dict[key]
            phi *= pow(key, value) - pow(key, value-1)
        return phi

  计算欧拉函数不是很困难,而在欧拉定理中,利用了欧拉函数的值。下面正式地介绍一下欧拉定理:

  • 欧拉定理:对于任意互素的正整数 a a a n n n有: a ϕ ( n ) ≡ 1 ( m o d    n ) a^{\phi(n)}\equiv 1(mod\;n) aϕ(n)1(modn),下面是定理的证明:

【证明】 a ϕ ( n ) ≡ 1 ( m o d    n ) a^{\phi(n)}\equiv 1(mod\;n) aϕ(n)1(modn)

  当 n = 1 n=1 n=1时明显成立,考虑 n > 2 n>2 n>2时,有 ϕ ( n ) \phi(n) ϕ(n)是指小于等于 n n n的与 n n n互素的正整数个数,那么考虑这些整数构成的集合 R = { x 1 , x 2 , x 3 , . . . , x ϕ ( n ) } R=\{x_1,x_2,x_3,..., x_{\phi(n)}\} R={ x1,x2,x3,...,xϕ(n)},而且 ∀ i ∈ { 1 , 2 , 3 , . . . , ϕ ( n ) } \forall i\in \{1, 2, 3,..., \phi(n)\} i{ 1,2,3,...,ϕ(n)} g c d ( x i , n ) = 1 gcd(x_i, n)=1 gcd(xi,n)=1,且不妨设 0 < x 1 < x 2 < x 3 < . . . < x ϕ ( n ) < n 0<x_1<x_2<x_3<...<x_{\phi(n)}<n 0<x1<x2<x3<...<xϕ(n)<n

  考虑 S = { ( a x 1    m o d    n ) , ( a x 2    m o d    n ) , ( a x 3    m o d    n ) , . . . , ( a x ϕ ( n )    m o d    n ) } S=\{(ax_1\;mod\;n),(ax_2\;mod\;n),(ax_3\;mod\;n),...,(ax_{\phi(n)}\;mod\;n)\} S={ (ax1modn),(ax2modn),(ax3modn),...,(axϕ(n)modn)},可知 ∀ i ∈ { 1 , 2 , 3 , . . . , ϕ ( n ) } \forall i\in \{1, 2, 3,..., \phi(n)\} i{ 1,2,3,...,ϕ(n)} a , x i a,x_i a,xi n n n互素,故 a x i ax_i axi n n n互素,根据欧几里得算法 g c d ( a x i , n ) = g c d ( n , a x i ( m o d    n ) ) = 1 gcd(ax_i, n)=gcd(n, ax_i(mod\;n))=1 gcd(axi,n)=gcd(n,axi(modn))=1,因此 S S S中的每一个元素都大于 0 0 0,小于 n n n,且与 n n n互素。

  同时 ∀ i , j ∈ { 1 , 2 , 3 , . . . , ϕ ( n ) } \forall i,j\in \{1, 2, 3,..., \phi(n)\} i,j{ 1,2,3,...,ϕ(n)},若 i ≠ j i\ne j i=j,那么 ( a x i    m o d    n ) ≠ ( a x j    m o d    n ) (ax_i\;mod\;n)\ne (ax_j\;mod\;n) (aximodn)=(axjmodn),否则 ( a x i    m o d    n ) = ( a x j    m o d    n ) ⇒ ( ( a − 1 ) × a x i    m o d    n ) = ( ( a − 1 ) × a x j    m o d    n ) ⇒ ( x i    m o d    n ) = ( x j    m o d    n ) ⇒ x i = x j (ax_i\;mod\;n)=(ax_j\;mod\;n)\Rightarrow ((a^{-1})\times ax_i\;mod\;n)=((a^{-1})\times ax_j\;mod\;n)\Rightarrow (x_i\;mod\;n)=(x_j\;mod\;n)\Rightarrow x_i=x_j (aximodn)=(axjmodn)((a1)×aximodn)=((a1)×axjmodn)(ximodn)=(xjmodn)xi=xj

  与 0 < x 1 < x 2 < x 3 < . . . < x ϕ ( n ) < n 0<x_1<x_2<x_3<...<x_{\phi(n)}<n 0<x1<x2<x3<...<xϕ(n)<n不合

  综上所述, S S S中有 ϕ ( n ) \phi(n) ϕ(n)个元素,每个元素都大于 0 0 0,小于 n n n,且与 n n n互素,则 R = S R=S R=S,那么有:

   x 1 × x 2 × . . . × x ϕ ( n ) = ( a x 1    m o d    n ) × ( a x 2    m o d    n ) × . . . × ( a x ϕ ( n )    m o d    n ) ⇒ a ϕ ( n ) ≡ 1 ( m o d    n ) x_1\times x_2\times...\times x_{\phi(n)}=(ax_1\;mod\;n)\times (ax_2\;mod\;n)\times ...\times (ax_{\phi(n)}\;mod\;n)\Rightarrow a^{\phi(n)}\equiv 1(mod\;n) x1×x2×...×xϕ(n)=(ax1modn)×(ax2modn)×...×(axϕ(n)modn)aϕ(n)1(modn)

  与费马小定理一样,欧拉定理也有另一种形式:

  • 欧拉定理另一形式:对于任意正整数 a a a n n n,若 n n n的素数分解不包括重复因子(即 n = p 1 n 1 p 2 n 2 p 3 n 3 . . . p t n t n=p_1^{n_1} p_2^{n_2} p_3^{n_3}... p_t^{n_t} n=p1n1p2n2p3n3...ptnt中素数的指数均为 1 1 1),则有 a ϕ ( n ) + 1 ≡ a ( m o d    n ) a^{\phi(n)+1}\equiv a(mod\;n) aϕ(n)+1a(modn)

  这一公式也十分有用,不过该公式的证明超出了本文讨论的范围。总结一下关于费马定理和欧拉定理的使用:

  对于费马定理和欧拉定理,如果计算 a x ≡ b ( m o d    n ) a^x\equiv b(mod\;n) axb(modn)中的一些参数,那么如果n是素数,那么考虑费马定理,若n不是素数则考虑欧拉定理,下面举两个例子介绍一下:

  1. 0 ≤ x ≤ 28 0\le x \le28 0x28,使得 x 85 ≡ 6 ( m o d    29 ) ? x^{85}\equiv 6(mod\;29)? x856(mod29)?

   29 29 29是素数,那么可以利用费马定理: x 29 ≡ x ( m o d    29 ) x^{29}\equiv x(mod\;29) x29x(mod29),由于 0 ≤ x ≤ 28 0\le x \le28 0x28,则 x x x 29 29 29互素,那么 x 29 − 1 ≡ 1 ( m o d    29 ) x^{29-1}\equiv 1(mod\;29) x2911(mod29),则 x 85 ≡ ( x 28 ) 3 × x ≡ x ≡ 6 ( m o d    29 ) x^{85}\equiv (x^{28})^3\times x\equiv x\equiv 6(mod\; 29) x85(x28)3×xx6(mod29),则 x = 6 x=6 x=6

  1. 0 ≤ a ≤ 9 0\le a \le9 0a9,使得 7 1000 ≡ a ( m o d    10 ) ? 7^{1000}\equiv a(mod\;10)? 71000a(mod10)?

   10 = 2 × 5 10=2\times 5 10=2×5,故 10 10 10不是素数,但 7 7 7 10 10 10互素,且 ϕ ( 10 ) = ϕ ( 2 ) × ϕ ( 5 ) = 4 \phi(10)=\phi(2)\times \phi(5)=4 ϕ(10)=ϕ(2)×ϕ(5)=4,那么由欧拉定理有 7 1000 ≡ ( 7 4 ) 250 ≡ 1 ≡ a ( m o d    10 ) 7^{1000}\equiv (7^4)^{250}\equiv 1\equiv a(mod\;10) 71000(74)2501a(mod10),则a = 1 =1 =1

2.1.3 素性检测

  从上面可以看到,素数具有很多良好的性质,而且在密码学中经常要找到一个足够大的素数(例如300位以上)。不过到目前为止还没有一个很好的素数检测算法,大多算法都是基于一定数学问题来筛选素数,这些算法大多不是一个确定性算法,即通过测试的整数不一定是素数,但大概率是一个素数,多次对一个素数进行检测可以以很高的概率认为这就是一个素数。下面给出一个检测素数的算法——MIller-Rabin算法,下面是算法的伪代码

Primetest(n)
输入:一个整数 n n n
输出:返回对该整数的素数判断,若 n n n可能是素数,则返回不确定,否则返回合数。
k ← 0 , q ← n − 1 k \leftarrow 0, q \leftarrow n-1 k0,qn1
w h i l e    q    m o d    2 = = 0 d o while\;q\;mod\;2 == 0\quad do whileqmod2==0do
k ← k + 1 \qquad k \leftarrow k+1 kk+1
q ← q / 2 \qquad q \leftarrow q /2 qq/2
a ← { 2 , 3 , . . . n − 1 } a \leftarrow \{2, 3, ...n-1\}\qquad \qquad a{ 2,3,...n1} // 从 2 ∼ n − 1 2\sim n-1 2n1中随机选择一个数
i f    a q    m o d    n = = 1 t h e n    r e t u r n    “ 不 确 定 ” if\;a^q\;mod\;n == 1\quad then\;return\;“不确定” ifaqmodn==1thenreturn
e l s e else else
f o r    j ← 0    t o    k − 1 d o \qquad for\;j \leftarrow 0\;to\;k-1\quad do forj0tok1do
i f    2 2 j q    m o d    n = = n − 1 t h e n    r e t u r n    “ 不 确 定 ” \qquad \qquad if\;2^{2^jq}\;mod\;n == n-1\quad then\;return\;“不确定” if22jqmodn==n1thenreturn
r e t u r n    “ 合 数 ” \qquad return\;“合数” return

  该算法是一个不确定算法,通过测试(返回不确定)的数不是素数的概率小于 1 / 4 1/4 1/4,因此多次对该数进行Miller-Rabin算法测试可以以很大的概率判断该数是素数。

2.2 中国剩余定理

  下面讨论一下中国古代数学家为数论作出的一些贡献:中国剩余定理(The Chinese Remainder Theorem,CRT)。中国剩余定理是由公元100年前的孙子发现的,其给出了大数运算的简便计算方法,中国剩余定理有两种形式,其常用的形式如下:

  令 m 1 , m 2 , m 3 , . . . , m k m_1, m_2, m_3,...,m_k m1,m2,m3,...,mk是两两互素的整数, M = ∏ i = 1 k m i M=\prod_{i=1}^{k}m_i M=i=1kmi,设 a 1 , a 2 , a 3 , . . . , a k a_1, a_2, a_3,...,a_k a1,a2,a3,...,ak是整数,则同余方程组在模M下有唯一解。
x ≡ a 1 ( m o d    m 1 ) x ≡ a 2 ( m o d    m 2 ) x ≡ a 3 ( m o d    m 3 ) . . . x ≡ a k ( m o d    m k ) x\equiv a_1(mod\; m_1)\\ x\equiv a_2(mod\; m_2)\\ x\equiv a_3(mod\; m_3)\\ ...\\ x\equiv a_k(mod\; m_k)\\ xa1(modm1)xa2(modm2)xa3(modm3)...xak(modmk)

  这种定义方式比较直观,但不能表现中国剩余定理的用途。下面给出一种有用的表达形式:

  令 M = ∏ i = 1 k m i M=\prod _{i=1}^km_i M=i=1kmi,其中 m i m_i mi是两两互素的, ∀ A ∈ Z M \forall A\in Z_M AZM,可将 A A A对应于一个 k k k元组 ( a 1 , a 2 , a 3 , . . . , a k ) (a_1, a_2, a_3,..., a_k) (a1,a2,a3,...,ak),即 A ⟷ ( a 1 , a 2 , a 3 , . . . , a k ) A\longleftrightarrow (a_1, a_2, a_3,..., a_k) A(a1,a2,a3,...,ak),其中 a i a_i ai有: a i ∈ Z m i a_i\in Z_{m_i} aiZmi a i = A    m o d    m i a_i=A\;mod\;m_i ai=Amodmi

  中国剩余定理第二种形式说明以下两种情况是成立的:

  • A ⟷ ( a 1 , a 2 , a 3 , . . . , a k ) A\longleftrightarrow (a_1, a_2, a_3,..., a_k) A(a1,a2,a3,...,ak)的映射是从 Z M Z_M ZM Z m 1 × Z m 1 × Z m 1 × . . . × Z m 1 Z_{m_1}\times Z_{m_1}\times Z_{m_1}\times ...\times Z_{m_1} Zm1×Zm1×Zm1×...×Zm1的一一对应(即双射)
  • Z M Z_M ZM中元素上的运算等价于对应于 k k k元组上的运算

  第一点中 A A A对应于 ( a 1 , a 2 , a 3 , . . . , a k ) (a_1, a_2, a_3,..., a_k) (a1,a2,a3,...,ak)是容易理解的,而 ( a 1 , a 2 , a 3 , . . . , a k ) (a_1, a_2, a_3,..., a_k) (a1,a2,a3,...,ak)如何对应 A A A呢,也就是如何计算 A A A的问题:

  对 1 ≤ i ≤ k 1\le i\le k 1ik,令 M i = M / m i M_i=M/m_i Mi=M/mi,故 M i M_i Mi m i m_i mi互素,而 ∀ j ≠ i , M i ≡ 0 ( m o d    m j ) \forall j\ne i,M_i\equiv 0(mod\;m_j) j=iMi0(modmj)。根据 M i M_i Mi m i m_i mi互素可知, M i M_i Mi在模 m i m_i mi运算下有乘法逆元 M i − 1 M_i^{-1} Mi1,故令 c i = M i × ( M i − 1    m o d    m i ) c_i=M_i\times (M_i^{-1}\;mod\;m_i) ci=Mi×(Mi1modmi),其中 1 ≤ i ≤ k 1\le i\le k 1ik,则有下面计算 A A A的公式: A ≡ ( ∑ i = 1 k a i c i ) ( m o d    M ) A\equiv (\sum_{i=1}^k{a_ic_i})(mod\;M) A(i=1kaici)(modM)

  不过得证明上式公式是正确的,也即证明 ∀ 1 ≤ i ≤ k ,    a i = A    m o d    m i \forall 1\le i\le k,\;a_i=A\;mod\;m_i 1ik,ai=Amodmi,将 A A A的公式代入计算则有:

   A    m o d    m i = ( ∑ i = 1 k a i c i ) ( m o d    m i ) = a i c i ( m o d    m i ) = a i × ( M i × ( M i − 1    m o d    m i ) ) ( m o d    m i ) = a i A\;mod\;m_i = (\sum_{i=1}^k{a_ic_i})(mod\;m_i)=a_ic_i(mod\;m_i)=a_i\times(M_i\times (M_i^{-1}\;mod\;m_i))(mod\;m_i)=a_i Amodmi=(i=1kaici)(modmi)=aici(modmi)=ai×(Mi×(Mi1modmi))(modmi)=ai

  其中利用了 ∀ j ≠ i , c j    m o d    m i = ( M j × ( M j − 1    m o d    m j ) ) ( m o d    m i ) = 0 \forall j\ne i,c_j\;mod\;m_i=(M_j\times (M_j^{-1}\;mod\;m_j))(mod\;m_i)=0 j=icjmodmi=(Mj×(Mj1modmj))(modmi)=0

  第二点的含义是:设有 A ⟷ ( a 1 , a 2 , a 3 , . . . , a k ) ,    B ⟷ ( b 1 , b 2 , b 3 , . . . , b k ) A\longleftrightarrow (a_1, a_2, a_3,..., a_k),\;B\longleftrightarrow (b_1, b_2, b_3,..., b_k) A(a1,a2,a3,...,ak),B(b1,b2,b3,...,bk),则有

  • ( A + B )    m o d    M ⟷ ( ( a 1 + b 1 )    m o d    m 1 , . . . , ( a k + b k )    m o d    m k ) (A+B)\;mod\;M\longleftrightarrow ((a_1+b_1)\;mod\;m_1,...,(a_k+b_k)\;mod\;m_k) (A+B)modM((a1+b1)modm1,...,(ak+bk)modmk)
  • ( A − B )    m o d    M ⟷ ( ( a 1 − b 1 )    m o d    m 1 , . . . , ( a k − b k )    m o d    m k ) (A-B)\;mod\;M\longleftrightarrow ((a_1-b_1)\;mod\;m_1,...,(a_k-b_k)\;mod\;m_k) (AB)modM((a1b1)modm1,...,(akbk)modmk)
  • ( A × B )    m o d    M ⟷ ( ( a 1 × b 1 )    m o d    m 1 , . . . , ( a k × b k )    m o d    m k ) (A\times B)\;mod\;M\longleftrightarrow ((a_1\times b_1)\;mod\;m_1,...,(a_k\times b_k)\;mod\;m_k) (A×B)modM((a1×b1)modm1,...,(ak×bk)modmk)

  下面用一个例子来解释一下:假设计算 ( 973 + 678 )    m o d    1813 (973+678)\;mod\;1813 (973+678)mod1813(这个数目不够大,仅仅作为演示),可知 M = 1813 = 37 × 49 M=1813=37\times 49 M=1813=37×49,令 m 1 = 37 , m 2 = 49 m_1=37, m_2=49 m1=37,m2=49,而且 37 37 37 49 49 49互素。

  首先计算 973 973 973 678 678 678对应的 k k k元组(这里是 2 2 2元组):

973 ⟷ ( 973    m o d    37 , 973    m o d    49 ) = ( 11 , 42 ) 678 ⟷ ( 678    m o d    37 , 678    m o d    49 ) = ( 12 , 41 ) 973 \longleftrightarrow (973\;mod\;37, 973\;mod\;49)=(11, 42)\\ 678 \longleftrightarrow (678\;mod\;37, 678\;mod\;49)=(12, 41) 973(973mod37,973mod49)=(11,42)678(678mod37,678mod49)=(12,41)

  因此 ( 973 + 678 )    m o d    1813 ⟷ ( ( 11 + 12 )    m o d    37 , ( 42 + 41 )    m o d    49 ) = ( 23 , 34 ) (973+678)\;mod\;1813\longleftrightarrow ((11+12)\;mod\;37, (42+41)\;mod\;49)=(23,34) (973+678)mod1813((11+12)mod37,(42+41)mod49)=(23,34)。那么还需要知道 ( 23 , 34 ) (23,34) (23,34)对应与 Z M Z_M ZM中的哪一个数,根据上面的推导 A = ( a 1 c 1 + a 2 c 2 ) ( m o d    M ) A=(a_1c_1+a_2c_2)(mod\;M) A=(a1c1+a2c2)(modM),下面计算有

a 1 = 23 ,    c 1 = M 1 × ( M 1 − 1    m o d    m 1 ) = 49 × ( − 3    m o d    37 ) = 1666 a 2 = 34 ,    c 2 = M 2 × ( M 2 − 1    m o d    m 2 ) = 37 × ( 4    m o d    49 ) = 148    a_1=23,\;c_1=M_1\times (M_1^{-1}\;mod\;m_1)=49\times (-3\;mod\;37)=1666\\ a_2=34,\;c_2=M_2\times (M_2^{-1}\;mod\;m_2)=37\times (4\;mod\;49)=148\quad\; a1=23,c1=M1×(M11modm1)=49×(3mod37)=1666a2=34,c2=M2×(M21modm2)=37×(4mod49)=148

  其中 m 1 = 37 , m 2 = 49 m_1=37,m_2=49 m1=37,m2=49 M 1 = M / m 1 = 49 , M 2 = M / m 2 = 37 M_1=M/m_1=49,M_2=M/m_2=37 M1=M/m1=49,M2=M/m2=37,而 M 1 − 1 M_1^{-1} M11 M 2 − 1 M_2^{-1} M21需要利用前述的扩展的欧几里得算法(1.1.3节)进行计算:

# 输入M1和m1得到M1的乘法逆元
Enter two numbers:49, 37                # M1 = 49,m1 = 37
gcd(49, 37) = 1 = (-3) * 49 + (4) * 37  # M1前面的系数即为乘法逆元,此处49前面的系数为-3
# 输入M2和m2得到M2的乘法逆元
Enter two numbers:37, 49                # M2 = 37,m2 = 49
gcd(49, 37) = 1 = (-3) * 49 + (4) * 37  # M2前面的系数即为乘法逆元,此处37前面的系数为4

  则 49 49 49 37 37 37运算的乘法逆元为 − 3 -3 3 37 37 37 49 49 49运算的乘法逆元为 4 4 4,即为上面的值。因此 A A A的值为: A = ( 23 × 1666 + 34 × 148 ) ( m o d    1813 ) = 1651 A=(23\times 1666+34\times 148)(mod\;1813)=1651 A=(23×1666+34×148)(mod1813)=1651

  可能你会觉得直接计算 ( 973 + 678 )    m o d    1813 (973+678)\;mod\;1813 (973+678)mod1813会更加简单,但是如果当 M M M很大时利用中国剩余定理将十分有用。

2.3 离散对数

  下面讲述离散对数问题(Discrete logarithms),离散对数问题是包括Diffie-Hellman密钥交换算法和数字签名算法(DSA)在内的许多公钥算法的基础,下面就来简单介绍一下离散对数问题。

2.3.1 本原根

  根据欧拉定理,对于任意互素的正整数a和n有: a ϕ ( n ) ≡ 1 ( m o d    n ) a^{\phi(n)}\equiv 1(mod\;n) aϕ(n)1(modn),考虑更一般的表达形式:对于任意 a a a n n n,有 m m m使得 a m ≡ 1 ( m o d    n ) a^m\equiv 1(mod\;n) am1(modn)

  当 a a a n n n互素时, m m m一定存在,至少 m = ϕ ( n ) m=\phi(n) m=ϕ(n)是成立的,因此有下面关于阶的概念:

  • a ( m o d    n ) a(mod\;n) a(modn)的阶:使得 a m ≡ 1 ( m o d    n ) a^m\equiv 1(mod\;n) am1(modn)成立的最小正幂 m m m a a a n n n的阶

  作为示例,下面给出模 19 19 19的正整数幂,需要注意表中行列的取值是十分讲究的,由于当 a a a n n n的阶 m m m存在时, a m ≡ 1 ( m o d    n ) a^m\equiv 1(mod\;n) am1(modn),因此计算正整数幂的时候,只需要计算 { 1 , 2 , 3 , . . . , m } \{1, 2, 3,...,m\} { 1,2,3,...,m},因为再往后一定与前面的值重复,即对于 t ∈ N t\in N tN i ∈ { 1 , 2 , . . . , ϕ ( n ) } i\in \{1,2,...,\phi(n)\} i{ 1,2,...,ϕ(n)} a t m + i a^{tm+i} atm+i可以表示所有正整数幂,且有 a t m + i ≡ a i ( m o d    n ) a^{tm+i}\equiv a^i(mod\;n) atm+iai(modn)

  下表由于事先不知道 m m m的值,故取 m = ϕ ( 19 ) = 18 m=\phi(19)=18 m=ϕ(19)=18,因为 19 19 19是素数,故对于 { 1 , 2 , 3 , . . . , 18 } \{1, 2, 3,...,18\} { 1,2,3,...,18}内的整数全与 19 19 19互素,因此这些整数模 19 19 19的阶 m ≤ ϕ ( 19 ) = 18 m\le\phi(19)=18 mϕ(19)=18,故下表的第一行只计算了 a 1 , a 2 , . . . , a 18 a^1, a^2,...,a^{18} a1,a2,...,a18

  而第一列中可以看到 a a a依次取值 { 1 , 2 , 3 , . . . , 18 } \{1, 2, 3,...,18\} { 1,2,3,...,18},大于 18 18 18的值之所以不考虑是因为以下两点:

  • m = 19 n ( n ∈ Z + ) m=19n(n\in Z^+) m=19n(nZ+)时, ∀ i ∈ { 1 , 2 , 3 , . . . , 18 } , m i    m o d    19 = 0 \forall i\in \{1, 2, 3,...,18\},m^i\;mod\;19=0 i{ 1,2,3,...,18},mimod19=0
  • m = 19 n + a ( n ∈ N , a ∈ { 1 , 2 , 3 , . . . , 18 } ) m=19n+a(n\in N, a\in \{1, 2, 3,...,18\}) m=19n+a(nN,a{ 1,2,3,...,18}) m i ≡ ( 19 n + a ) i ( m o d    19 ) ≡ a i ( m o d    19 ) m^i\equiv (19n+a)^i(mod\;19)\equiv a^i(mod\;19) mi(19n+a)i(mod19)ai(mod19)

  因此只计算下表即可知道所有的情况

  观察上表,我们发现所有序列都是以 1 1 1为结尾,此时对应的 m m m即为 a a a n n n的阶,在 1 1 1之前的数都各不相同,在 1 1 1之后的数则出现了周期性的重复。另外对于一些整数来说,比如 2 , 3 , 10 , 13 , 14 , 15 2,3,10,13,14,15 2,3,10,13,14,15而言,它们的正整数幂的值互不相同,包含了 { 1 , 2 , 3 , . . . , 18 } \{1, 2, 3,...,18\} { 1,2,3,...,18},称这样的整数为模数 19 19 19的本原根,下面就是本原根的形式化定义:

  • 本原根 a a a称为模数 n n n的本原根,当且仅当 a a a n n n的阶为 ϕ ( n ) \phi(n) ϕ(n)

  下面证明一下本原根的一个性质:若 a a a是模数 n n n的本原根,那么 { a 1 , a 2 , . . . , a ϕ ( n ) }    m o d    n \{a^1, a^2,...,a^{\phi(n)}\}\;mod\;n { a1,a2,...,aϕ(n)}modn各不相同,且均与 n n n互素。

【证明】若 a a a是模数 n n n的本原根,那么 { a 1 , a 2 , . . . , a ϕ ( n ) }    m o d    n \{a^1, a^2,...,a^{\phi(n)}\}\;mod\;n { a1,a2,...,aϕ(n)}modn各不相同,且均与 n n n互素。

   a a a的正整数幂各不相同是容易理解的,因为若当 1 ≤ i < j ≤ ϕ ( n ) 1\le i<j\le\phi(n) 1i<jϕ(n) a i ≡ a j ( m o d    n ) a^i\equiv a^j(mod\;n) aiaj(modn),根据 a i a^i ai与n互素知 a j − i ≡ 1 ( m o d    n ) a^{j-i}\equiv 1(mod\;n) aji1(modn),则a模n的阶为 j − i ≤ ϕ ( n ) j-i\le \phi(n) jiϕ(n)与a模n的阶是 ϕ ( n ) \phi(n) ϕ(n)矛盾,这个推理用到了 a i a^i ai与n互素的假设。

  下面来证明 { a 1 , a 2 , . . . , a ϕ ( n ) }    m o d    n \{a^1, a^2,...,a^{\phi(n)}\}\;mod\;n { a1,a2,...,aϕ(n)}modn均与 n n n互素,假设 ∃ i ∈ { 1 , 2 , . . . , ϕ ( n ) } \exist i\in \{1,2,...,\phi(n)\} i{ 1,2,...,ϕ(n)}使得 a i m o d    n a^imod\;n aimodn n n n不互素,那么 g c d ( ( a i    m o d    n ) , n ) = r > 1 gcd((a^i\;mod\;n), n)=r>1 gcd((aimodn),n)=r>1,而根据欧几里得算法有 g c d ( a i , n ) = g c d ( n , ( a i    m o d    n ) ) gcd(a^i, n)=gcd(n,(a^i\;mod\;n)) gcd(ai,n)=gcd(n,(aimodn)),故 a i m o d    n a^imod\;n aimodn与n不互素等价于 a i a^i ai与n不互素,但是 a i a^i ai与n不互素说明 a i , a i + 1 , . . . , a ϕ ( n ) a^i, a^{i+1},...,a^{\phi(n)} ai,ai+1,...,aϕ(n)均与n不互素,而 a ϕ ( n ) ≡ 1 ( m o d    n ) a^{\phi(n)}\equiv 1(mod\;n) aϕ(n)1(modn),故 a ϕ ( n )    m o d    n a^{\phi(n)}\;mod\;n aϕ(n)modn与n互素,也即 a ϕ ( n ) a^{\phi(n)} aϕ(n) n n n互素,故假设不成立,则 a i a^i ai n n n互素。

  既然如此,那么考察两个集合 R = { ( a 1    m o d    n ) , ( a 2    m o d    n ) , . . . , ( a ϕ ( n )    m o d    n ) } R=\{(a^1\;mod\;n), (a^2\;mod\;n),...,(a^{\phi(n)}\;mod\;n)\} R={ (a1modn),(a2modn),...,(aϕ(n)modn)}和集合 X X X,集合 X X X是与小于等于 n n n,且与 n n n互素的正整数的集合,设 X = { x 1 , x 2 , x 3 , . . . , x ϕ ( n ) } X=\{x_1,x_2,x_3,..., x_{\phi(n)}\} X={ x1,x2,x3,...,xϕ(n)}

  当 n = 1 n=1 n=1时,显然有 R = X R=X R=X,考虑 n > 2 n>2 n>2,由上面的推理可知, R R R ϕ ( n ) \phi(n) ϕ(n)个元素,且所有元素小于 n n n n n n互素,恰好满足集合 X X X的定义( n > 2 n>2 n>2 X X X内的元素只能小于 n n n),那么 R = X R=X R=X,综上 R = X R=X R=X

  不过上面本原根的定义十分抽象,根据上面的证明可以发现本原根更直观的定义就是:

  • 本原根:设 X X X为小于等于 n n n且与 n n n互素的正整数集合,即 X = { x 1 , x 2 , x 3 , . . . , x ϕ ( n ) } X=\{x_1, x_2, x_3, ..., x_{\phi(n)}\} X={ x1,x2,x3,...,xϕ(n)},其中 ∀ i ∈ { 1 , 2 , 3 , . . . , ϕ ( n ) } \forall i\in\{1, 2, 3, ..., \phi(n)\} i{ 1,2,3,...,ϕ(n)} g c d ( x i , n ) = 1 gcd(x_i, n)=1 gcd(xi,n)=1 a a a n n n的本原根当且仅当集合 { ( a 1    m o d    n ) , ( a 2    m o d    n ) , . . . , ( a ϕ ( n )    m o d    n ) } = X \{(a^1\;mod\;n), (a^2\;mod\;n),...,(a^{\phi(n)}\;mod\;n)\}=X { (a1modn),(a2modn),...,(aϕ(n)modn)}=X

  从两个定义看,求解本原根的过程是复杂的,而且不是所有整数都有本原根,可以证明(这里不证),只有形式 2 , 4 , p α , 2 p α 2,4,p^{\alpha },2p^{\alpha } 2,4,pα,2pα的整数才有本原根,其中 p p p是任意奇素数,$\alpha $为正整数。

2.3.2 离散对数难题

  引入本原根的概念,其实是为了介绍离散对数问题,对于对数大家是不陌生的,对数函数 y = l o g a x ( a > 0 , a ≠ 1 ) y=log_ax(a>0,a\ne 1) y=logax(a>0,a=1)和指数函数 y = a x ( a > 0 , a ≠ 1 ) y=a^x(a>0,a\ne 1) y=ax(a>0,a=1)是一对反函数,那么从这个定义出发,根据本原根的定义,对于一个素数 p p p(本原根定义中不要求素数)而言,可以发现,小于等于素数p且与之互素的正整数集合为 { 1 , 2 , . . . , p − 1 } \{1,2,...,p-1\} { 1,2,...,p1},故设 a a a为本原根,则 a a a满足:
{ ( a 1    m o d    p ) , ( a 2    m o d    p ) , . . . , ( a ϕ ( p )    m o d    p ) } = { ( a 1    m o d    p ) , ( a 2    m o d    p ) , . . . , ( a p − 1    m o d    p ) } = { 1 , 2 , . . . , p − 1 } \{(a^1\;mod\;p),(a^2\;mod\;p),...,(a^{\phi (p)}\;mod\;p)\} \\ = \{(a^1\;mod\;p),(a^2\;mod\;p),...,(a^{p-1}\;mod\;p)\} \\ = \{1,2,...,p-1\}\qquad\qquad\qquad\qquad\qquad\qquad { (a1modp),(a2modp),...,(aϕ(p)modp)}={ (a1modp),(a2modp),...,(ap1modp)}={ 1,2,...,p1}

  而对于任何整数 b b b b    m o d    p ∈ { 1 , 2 , . . . , p − 1 } b\;mod\;p\in \{1,2,...,p-1\} bmodp{ 1,2,...,p1},故 ∃ i ∈ { 1 , 2 , . . . , p − 1 } \exist i\in \{1,2,...,p-1\} i{ 1,2,...,p1}使得 a i ≡ b ( m o d    p ) a^i\equiv b(mod\;p) aib(modp),此时 i i i就被称为以 a a a为底模 p p p运算的 b b b的离散对数,记作 i = d l o g a , p b i=dlog_{a,p}b i=dloga,pb

  • 离散对数:若 a i ≡ b ( m o d    p ) a^i\equiv b(mod\;p) aib(modp),此时 i i i就被称为以 a a a为底模 p p p运算的 b b b的离散对数,记作 i = d l o g a , p b i=dlog_{a,p}b i=dloga,pb

  不过离散对数是基于本原根的概念,只有存在本原根时才存在唯一的以 a a a为底模 m m m的离散对数,而模数 m m m一般选为素数,因为素数存在本原根,下面给出以 2 2 2为底( 2 2 2 29 29 29的本原根)模 29 29 29的离散对数 d l o g 2 , 29 a dlog_{2,29}a dlog2,29a:

a a a 1 2 3 4 5 6 7 8 9 10 11 12 13 14
d l o g 2 , 29 a dlog_{2,29}a dlog2,29a 28 1 5 2 22 6 12 3 10 23 25 7 18 13
a a a 15 16 17 18 19 20 21 22 23 24 25 26 27 28
d l o g 2 , 29 a dlog_{2,29}a dlog2,29a 27 25 21 11 9 24 17 26 20 8 16 19 15 14

  基于上面的讨论,给出求解正整数 n n n的本原根的算法实现:

# 利用Euclid算法计算最小公因数gcd(a, b)
def Euclid_gcd(a, b):
    r1 = max(abs(a), abs(b))
    r2 = min(abs(a), abs(b))
    if r2 == 0:
        return r1
    else:
        return Euclid_gcd(r2, r1%r2)

# 求与小于等于n且与n互素的正整数集合
n = eval(input("Please enter a number: "))
X = set()
for i in range(1, n, 1):
    if Euclid_gcd(i, n) == 1:
        X.add(i)

# 求解n的本原根
for i in range(1, n, 1):
    A = set()
    for j in range(1, len(X)+1):
        A.add(pow(i, j, n))       # pow(i, j, n)计算了i^j mod n
    if A == X:
        print(i, end = " ")

  下面阐述一下基于离散对数的困难问题,对于方程 y = g x    m o d    p y=g^x\;mod\;p y=gxmodp,已知 g , x , p g,x,p g,x,p可以很容易计算 y y y,而已知 y , g , p y,g,p y,g,p很难计算 x x x,是指数级别复杂度的,比如你在上面的程序中想要计算 2 127 − 1 2^{127}-1 21271 39 39 39位的素数)的本原根,程序可能会运行很久,问题就在于计算一次 g x    m o d    p g^x\;mod\;p gxmodp最坏要 g g g次乘法,最好也要 l o g ( g ) log(g) log(g)次乘法,下面给出计算 g x    m o d    p g^x\;mod\;p gxmodp比较有效的算法:

def square(n):
    return n*n

# 计算g^x mod p
def exp_mod(g, x, p):
    if x == 0:
        return 1
    if x % 2 == 0:
        return square(exp_mod(g, x//2, p)) % p    # x是偶数,g^x mod p = (g^(x/2) mod p)^2 mod p
    else:
        return (g * exp_mod(g, x-1, p)) % p       # x是奇数,g^x mod p = ((g^(x-1) mod p)*g) mod p

g, x, p = eval(input("Please Enter three number:"))
print(exp_mod(g, x, p))

猜你喜欢

转载自blog.csdn.net/Stu_YangPeng/article/details/118872826