마지막 나눗셈에서는 rn−1이 rn으로 나누어 떨어진다. 이는 유클리드 알고리즘의 기저 사례라고 할 수 있다.
임의의 0이 아닌 정수 m에 대해 (m,0)=m이기 때문이다. 유클리드 알고리즘을 통해 (a,b)=rn임을 알 수 있다.
나눗셈 열에서 rm=0이 등장하여 알고리즘이 유한한 수행을 통해 정지한다는 사실은, 수열 b>r1>r2>⋯가 감소하는 음이 아닌 정수 수열을 이룸을 관찰함으로써 알 수 있다.
구현
유클리드 알고리즘을 다음과 같이 구현할 수 있다.
intgcd(int a,int b){if(b ==0)return a;returngcd(b, a % b);}
이는 꼬리 재귀 함수이다. 마음이 편안해진다.
일단 재귀 함수로 구현을 하였지만, 재귀 함수의 호출은 종종 많아져서는 메모리를 터뜨리게 된다.
알고리즘에 등장하는 나눗셈 열이 얼마나 길게 이어지는지 알아보기 위해 알고리즘을 분석하여 보자.
분석
입력이 a≥b으로 주어졌다고 가정하자. 피보나치 수열을 사용하여 k의 증가에 따라 rk가 지수적으로 감소한다는 사실을 증명할 것이다.
피보나치 수열은 점화식을 통해 주어지는 수열으로,
⎩⎨⎧f0f1fn=0,=1,=fn−1+fn−2(n≥2)
를 만족한다. b<fk가 되는 정수 k를 선택하고, 표기의 편의를 위해 r0=b로 설정하자. r1<fk−1임을 보이고 싶지만, 이는 간단한 반례를 통해 반증될 수 있는 명제이다. (23,12)를 유클리드 알고리즘을 통해 계산하는 상황을 생각하면, 처음 설정하는 피보나치 수는 f7=13이다. r1=11≥8=f6이므로 r1<fk−1는 거짓이다.
그러나 이가 거짓일 때 관찰할 수 있는 사실이 하나 있다. 위의 예시에서 나눗셈을 한 번 더 진행하여 보자. r2=1<5=f5임을 알 수 있다. 사실은 r1<fk−1이 거짓인 경우, r2<fk−2는 항상 참이다. 임의의 m에 대해, rm<fk이고 rm+1≥fk−1을 가정하자. 다음을 관찰하자:
rm+2≤rm−rm+1<fk−fk−1=fk−2.
따라서 r0<fk인 정수 k에 대해, 유클리드 알고리즘은 많아야 k+1번의 나눗셈을 수행할 것이다. fk∈O(φk),φ=21+5이므로, 유클리드 알고리즘은 O(logr0)의 시간복잡도를 갖는다.
확장된 유클리드 알고리즘
개요: 디오판토스 방정식 ax+by=(a,b)
임의의 두 정수 a,b에 대해 ax+by=(a,b)를 만족하는 정수 x,y가 존재한다. 정수 집합의 정렬성을 이용하여 증명할 수 있으나, 유클리드 알고리즘을 이용하여 증명하는 것이 좀 더 와닿는다고 생각한다. 우선 정수의 부분집합 S={ax+by:x,y∈Z}를 생각하자. 분명하게 a=r−1,b=r0∈S이다. S에 대해 다음 성질들을 관찰하자.
S는 덧셈에 대해 닫혀있다. S의 임의의 두 원소 ax+by,au+bv에 대해
(ax+by)+(au+bv)=a(x+u)+b(y+v)∈S
이다.
S는 상수배 곱셈에 대해 닫혀있다. S의 임의의 원소 ax+by와 임의의 정수 d에 대해
d(ax+by)=a(dx)+b(dy)∈S
이다.
이러한 성질에 의해, 임의의 k에 대해 rk−2,rk−1이 S에 포함된다면 rk=rk−2−qkrk−1또한 S에 포함됨을 알 수 있다. r−1,r0∈S이므로 수학적 귀납법을 통해 rn=(a,b)∈S임을 알 수 있다.
한편, 디오판토스 방정식 ax+by=(a,b)에는 항상 정수해 x,y가 존재한다는 정리를 베주 항등식Bézout's identity으로 부르기도 한다.
유클리드 알고리즘과 디오판토스 방정식 ax+by=(a,b)
디오판토스 방정식 ax+by=(a,b)는 정수해를 가짐을 보였다. 유클리드 알고리즘은 단지 이 방정식에서 정수해가 존재하는지 알려줄 뿐 만 아니라, 정수해를 계산할 수 있는 방법을 제시한다.
우선 a=r−1,b=r0라고 하자. i=−1,0,1,⋯,n에 대해 ri∈S임을 보였으므로, asi+bti=ri를 만족하는 정수 si,ti가 존재할 것이다. rk=rk−2−rk−1qk를 관찰하자. sk−2,sk−1,tk−2,tk−1으로 부터 sk,tk를 각각 다음과 같이 계산할 수 있다.
{sktk=sk−2−sk−1qk=tk−2−tk−1qk
r−1=a⋅1+b⋅0,r0=a⋅0+b⋅1은 쉽게 구할 수 있으므로, sn과 tn을 총 n번의 나눗셈을 통해 계산할 수 있다.
구현
기존에 구현하였던 유클리드 알고리즘에 sn과 tn을 계산하는 기능을 추가하여 보자. 자료를 쉽게 다루기 위해서 다음고 같은 구조체를 정의한다.
structeucPair{int x;int s, t;};
x에는 rk의 값이, s,t에는 각각 rk를 a,b의 선형결합으로 나타내었을 때의 계수가 저장된다. 위에서 구한 점화식과 유클리드 알고리즘을 이용하여 디오판토스 방정식을 해결하는 알고리즘은 다음과 같다.
PS 또는 정수론 문제들을 풀게 된다면 이러한 형태의 디오판토스 방정식의 해를 구해야 하는 일이 종종 생긴다. 주어진 정수 a에 대해, ax≡1(modn)을 만족하는 정수 x를 법 n에 대한 a의 잉여역수라고 하고, x=a−1으로 표기한다. (Z/nZ)×에서 x는 a의 역원이기 때문에 이러한 표기법을 사용한다. 이러한 x를 찾는 문제는 이변수 선형 디오판토스 방정식으로 변형될 수 있다. ax+ny=1을 만족하는 정수 x,y를 찾는 문제와 같기 때문이다. 확장된 유클리드 알고리즘을 사용하면 a의 잉여역수를 O(logn)의 시간복잡도로 찾을 수 있다. 물론, (a,n)>1이라면 잉여역수를 찾을 수 없을 것이다.