logo

ユークリッドの互除法の証明 📂整数論

ユークリッドの互除法の証明

アルゴリズム

二つの整数aba \ge bに対して、gcd(a,b)\text{gcd}(a,b)は以下のように求めることができる。

疑似コード

アルゴリズム:ユークリッドの互除法
入力整数a,ba, bが与えられる。
1.r0ar_{0} \gets a
2.r1br_{1} \gets b
3.while ri+10r_{i+1} \ne 0
4.  以下が成り立つようにqiq_iと新しいri+1r_{i+1}を続けて求める。ri1=riqi+ri+1,(ri>ri+1)r_{i-1} = r_i \cdot q_i + r_{i+1} \qquad , (r_i>r_{i+1})
5.  ii+1i \gets i+1
6.end while
出力aabb最大公約数gcd(a,b)\gcd (a,b)を得る。

定理

ri<ri+1 r_i<r_{i+1}に対して、ri1=qi+1ri+ri+1r_{i-1} = q_{i+1} \cdot r_{i} + r_{i+1}の漸化式を満たすa:=r1a: = r_{-1}b:=r0b:=r_{0}を定義しよう。rn+1=0r_{n+1} = 0を満たすnnの最小公倍数は以下の通りである。 rn=gcd(a,b) r_{n} = \gcd (a,b) このアルゴリズムは、多くとも2log2(b)+1 2 \log _2 (b) + 1 回以内に答えを見つけることができる。

説明

いわゆるユークリッドの互除法euclidean Algorithmとして知られるこのアルゴリズムは、最大公約数を非常に効率的に求めることができる。一つ一つ素因数分解をしなくても答えを出すため、数が大きくなるほどその真価を発揮する。

上でまとめられたアルゴリズムは、ユークリッドの原典をそのまま翻訳したものにすぎず、コードはもっと簡単に書くことができる。

証明 1

a=r0=bq1+r1b=r1=r2q2+r3ri=ri+1qi+1+ri+2rt1=rtqt \begin{align*} a = r_{0} =& b \cdot q_1 + r_1 \\ b = r_{1} =& r_2 \cdot q_2 + r_3 \\ &\vdots \\ r_i =& r_{i+1} \cdot q_{i+1} + r_{i+2} \\ &\vdots \\ r_{t-1} =& r_t \cdot q_t \end{align*} とする。与えられた条件 ri1=riqi+ri+1,(ri>ri+1) r_{i-1} = r_i \cdot q_i + r_{i+1} \qquad , (r_i>r_{i+1}) から、ri1r_{i-1}ri r_i約数ri+1r_{i+1}約数でもあることがわかる。よって、 gcd(ri1,ri)=gcd(ri,ri+1) \text{gcd}( r_{i-1} , r_i )=\text{gcd}( r_i , r_{i+1} ) である。一方で、rt1=rtqt,(rt+1=0)r_{t-1} = r_t \cdot q_t \qquad , (r_{t+1}=0)について考えると、 gcd(rt1,rt)=gcd(rtqt,rt)=rt \text{gcd}( r_{t-1} , r_t )=\text{gcd}( r_t \cdot q_t , r_t ) = r_t 今、必要な時間、つまり必要な回数を求めよう。その前に、ri+2<12ri\displaystyle r_{i+2} < {1 \over 2} r_iであることを示さなければならない。

  • ri+112rir_{i+1} \le {1 \over 2} r_iの場合
    ri+2<ri+112rir_{i+2} < r_{i+1} \le {1 \over 2} r_i
  • ri+1>12rir_{i+1} > {1 \over 2} r_i の場合
    ri=ri+11+ri+2r_i = r_{i+1} \cdot 1 + r_{i+2} 故に、 ri+2=riri+1<ri12ri12ri r_{i+2} = r_i - r_{i+1} < r_i - {1 \over 2} r_i \le {1 \over 2} r_i である。まとめると、 ri+2<12ri r_{i+2} < {1 \over 2} r_i と、上記の不等式により、 b=r1>2r3>22r5>>2kr2k+1 \begin{align*} b &= r_1 \\ &> 2 \cdot r_3 \\ &> 2^2 \cdot r_5 \\ &> \cdots \\ &> 2^k \cdot r_{2k+1} \end{align*} である。まとめると、 b>2kr2k+1 b > 2^k \cdot r_{2k+1} 一方、2kb2^k \ge bであるために、r2k+1<1r_{2k+1} < 1でなければならず、それはつまり、 r2k+1=0 r_{2k+1} = 0 である。また、t+12k+1t+1 \le 2k +1であるために、 t2k t \le 2k つまり、アルゴリズムを終了するのに必要な合計回数は、tt以下であり、 t2k=2(k1)+2<2log2(b)+2 t \le 2k = 2(k-1) + 2 < 2 \log _2 (b) + 2 よって、必要な回数は多くとも以下のようである。 2log2(b)+1 2 \log _2 (b) + 1

実装

以下はRコードで書かれたユークリッドの互除法の実装である。上はアルゴリズムをそのまま翻訳したバージョンで、下は不必要な部分を取り除いてすっきりと整理したバージョンである。

gcd<-function(a,b)
{    
    if (b>a) {i=b; b=a; a=i;}
    i=2
     r=numeric(0)
    r[1]=b
    r[2]=a%%b
    while(r[i]!=0)
    {
        r[i+1]=r[i-1]%%r[i]
        i=i+1
    }
    return(r[i-1])
}
 
gcd <- function(a, b) {
  if (b>a) {i=b; b=a; a=i;}
  while(b) {
    temp = b
    b = a %% b
    a = temp
  }
  return(a)
}

  1. Silverman. (2012). A Friendly Introduction to Number Theory (4th Edition): p34. ↩︎