Processing math: 100%

ユークリッド互除法

2数の最大公約数を求める。

拡張ユークリッド互除法

2数 x,y の最大公約数 gcd(x,y) とともに、

ax+by=gcd(x,y)

となる (a,b) の組の1つも見つける。

組の1つが見つかれば、後は u=xgcd(x,y),v=ygcd(x,y) として

...,(a2v,b+2u),(av,b+u),(a,b),(a+v,bu),(a+2v,b2u),...

が過不足なく全て等式を満たす組となる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 引用(もといパクリ)
# Python で RSA 公開鍵暗号をなぞってみる - CAMPHOR- Tech Blog
 
def ex_euclid(x, y):
    c0, c1 = x, y
    a0, a1 = 1, 0
    b0, b1 = 0, 1
 
    while c1 != 0:
        m = c0 % c1
        q = c0 // c1
 
        c0, c1 = c1, m
        a0, a1 = a1, (a0 - q * a1)
        b0, b1 = b1, (b0 - q * b1)
 
    return c0, a0, b0

ユークリッドの互除法の調整

互除法とは直接関係ないが、一緒に使うことがある制約条件について。

  • x,y,z から、ax+by=z となる a,b を求める
  • ただし a0,b0
  • a をあり得る中で最小にする

a,b が正という条件で全探索する時、a を最小(最大でもいいが)にしておくとやりやすい。

まず、c=gcd(x,y) として、zc の倍数で無い場合、等式は不可能である。

次に、拡張ユークリッド互除法で ax+by=c となる a,b を求める。w=zc とすると、axw+byw=cw=z となり、(a,b)=(aw,bw) が答えの一つとなる。

その後、非負チェックと a の最小化を行う。av=yc 単位でしか増減できないので a%v が最小値となる。負の場合だが、pythonでは a が負であっても a%v で正の最小値が求まる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def exex_euclid(x,y):
    c, a, b = ex_euclid(x, y)
    w, m = divmod(z, c)
     
    # zがcの倍数でないなら等式は不可能
    if m != 0:
        return None
         
    u, v = x // c, y // c
    a, b = a * w, b * w
 
    # aを非負数の中で最小にする
    f, a = divmod(a, v)
    b += u * f
     
    # aを最小にしたのにbが負なら、ともに正の組は不可能
    if b < 0:
        return None
 
    return c, a, b, u, v

programming_algorithm/number_theory/euclidean_algorithm.txt · 最終更新: 2018/06/14 by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0