拡張ユークリッド互除法で gcd(a,b) および ax+by=gcd(a,b) の整数解 (x0,y0) を得るコードを書いているのですが、x0 および y0 の大きさを数学的に評価する方法が知りたいです。
コードのverifyのために Aizu Online Judge (AOJ) の NTL_1_E 問題 を利用しているのですが、この問題では整数解について以下の条件が課されています:
「|x|+|y| が最小のものを出力する。最小のものが複数ある場合はその中で x ≤ y であるものを出力する。」
質問は以下の通りです:
- 拡張ユークリッド互除法は常に上記条件を満たす解を与えるのか?
- もしそうならば、それはどのように証明するのか?
- 私のコードは上記条件を常に満たすか?
私のコードは以下の通りです(一応AOJ上では正解と判定されましたが、テストケースに負数や0が含まれていないこともあり、本当に上記の条件が満たされているのか確信が持てません)
C++
1/** 2 * 蟻本のコードを負の引数も正しく処理できるようにしたもの 3 */ 4 5#include <bits/stdc++.h> 6 7using namespace std; 8 9int sgn(int x) { 10 if(x > 0) 11 return 1; 12 else if(x < 0) 13 return -1; 14 else 15 return 0; 16} 17 18int extgcd_impl(int a, int b, int& x, int& y) { 19 int d = a; 20 if(b != 0) { 21 d = extgcd_impl(b, a%b, y, x); 22 y -= (a/b) * x; 23 } 24 else { 25 x = 1; y = 0; 26 } 27 return d; 28} 29 30int extgcd(int a, int b, int& x, int& y) { 31 int d = extgcd_impl(abs(a), abs(b), x, y); 32 x *= sgn(a); 33 y *= sgn(b); 34 return d; 35} 36 37int main() { 38 int a, b; 39 cin >> a >> b; 40 41 int x, y; 42 int g = extgcd(a, b, x, y); 43 44 //cout << g << "\n"; 45 cout << x << " " << y << "\n"; 46 47 return 0; 48}
2019/02/25 追記:
StackExchange の記事 を参考にしつつ証明を考えてみました。あまりこういうのは書いたことがないので、間違っていたらご指摘いただきたいです。正しいという確信が得られるまでもうしばらく回答を受け付けたいと思います。
2019/02/27 追記: 〆切ました。
extgcd が問題の条件を満たす解を与えることの証明
※gcd(0,0)=0 と定義する。
a,b を整数とする。g=gcd(a,b) および ax+by=g の整数解 (X,Y) を求める関数 extgcd(a,b)=(g,X,Y) を考える。
|X|+|Y| が最小の解を最小解と呼ぶ(唯一とは限らない)。
- extgcd(a,b)=(g,X,Y) ならば extgcd(-a,b)=(g,-X,Y), extgcd(a,-b)=(g,X,-Y) なので、a>=0, b>=0についてのみ考えれば十分。
- gcd(a,b)>1 のとき、a=ga', b=gb' とおくと、ax+by=g は a'x+b'y=1 に帰着する。よって、gcd(a,b)<=1 についてのみ考えれば十分。
- extgcd(a,b)=(g,X,Y) ならば extgcd(b,a)=(g,Y,X) なので、a>=b についてのみ考えれば十分。
- extgcd(0,0)=(0,0,0), extgcd(1,0)=(1,1,0), extgcd(1,1)=(1,0,1) と定義する。いずれも最小解になっている。
以上より、後は gcd(a,b)=1, a>b>=2 についてのみ考えれば十分。
extgcd(a,b)=(1,X,Y) とする。a を b で割って a=qb+r と表す (0<r<b)
extgcd(b,r)=(1,X',Y') ならば、bX'+rY'=1 に r=a-qb を代入して
X=Y', Y=X'-qY' が得られる。
このとき、|X|<=b/2, |Y|<=a/2 が成り立つことを帰納法で示す。
g=gcd(a,b)=1 だから、extgcdの再帰呼び出し中のある時点で第2引数が1になる。この直前の extgcd(A,B) を考える。
A=QB+1, A>B>=2 である。
extgcd(B,1)=(1,0,1) より、extgcd(A,B)=(1,1,-Q) である。よって
|1|<=B/2, |-Q|=Q<=QB/2<A/2 より、A,B については命題は成り立っている。
次に一般の a,b について考える。a=qb+r, extgcd(a,b)=(1,X,Y) とする。
extgcd(b,r)=(1,X',Y'), |X'|<=r/2, |Y'|<=b/2 ならば、
|X|=|Y'|<=b/2
|Y|=|X'-qY'|<=|X'|+|qY'|<=r/2+qb/2=(qb+r)/2=a/2
より、a,b についても命題は成り立つ。
よって命題は gcd(a,b)=1, a>b>=2 なる全ての a,b について成り立つ。
ところで、ax+by=1 の一般解は (x,y)=(X+mb,Y-ma) と表せる。
|X|<=b/2 より、m!=0 のとき |X+mb|>=|X|
|Y|<=a/2 より、m!=0 のとき |Y-ma|>=|Y|
なので、X,Y は最小解である。最小解が他に存在するためには |X|=b/2, |Y|=a/2 でなければならず、このとき aX+bY は ab, 0, -ab のいずれかになるが、いずれも gcd(a,b)=1 に反する。よって、gcd(a,b)=1, a>b>=2 のとき、ax+by=1 の最小解は唯一である。
他に最小解が複数存在しうるのは (a,b)=(1,1) のみであり、このとき ax+by=1 の最小解は (1,0),(0,1) の2通りある。しかし extgcd(1,1)=(1,0,1) と定義したから、X<=Y は満たされている。
結局、この extgcd の定義では常に最小解が得られ、最小解が複数ある場合は X<=Y なるものが得られる。証明終
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/02/25 05:04
2019/02/25 05:09
2019/02/25 08:11
2019/02/25 13:39
2019/02/26 15:33