1

ax+by=1の整数解(ユークリッドの互除法)

370
0

ax+by=1の整数解

はじめに

ax+by=1の整数解をみつける方法として、ユークリッドの互除法を利用する方法がある。
高校時代は手順がいまいち理解できていなかったので、自分なりにまとめてみようと思います。

前提と表記

場合分けが面倒なので、特に断りがなければ以下を前提とする。

  • a>0b>0
  • a>b
  • abは互いに素

ax+by=0の整数解

ax+by=1 の整数解を求める前段階として
ax+by=0の整数解について考える

ax+by=0 の整数解

方程式
ax+by=0
の整数解は、整数 m を用いて
x=mby=ma
と表すことができる。

abは互いに素なので、xbの倍数。よって x=mbとおける。
これを方程式に代入すると
a(mb)+by=0
b(ma+y)=0
b0なので
ma+y=0
y=ma

ユークリッドの互除法(表)

step数式1数式2v
1a=bq1+r1abq1=r1v1=(1,0)(0,1)q1
2b=r1q2+r2br1q2=r2v2=(0,1)v1q2
3r1=r2q3+r3r1r2q3=r3v3=v1v2q3
4r2=r3q4+r4r2r3q4=r4v4=v2v3q4
krk2=rk1qk+rkrk2rk1qk=rkvk=vk2vk1qk
nrn2=rn1qn+1rn2rn1qn=1vn=vn2vn1qn

表の解説

  • 数式1 互除法の操作。abは互いに素なので最終的なあまりは1
  • 数式2 数式1を変形したもの。左辺を「a+b」のかたちで表すことができれば、
        最終行が所望の式のかたちになり、1組の整数解を得る。
  • v   a=(1,0)b=(0,1)とおいて数式2を計算したときにrkに相当するベクトルをvkとする。
        このベクトルはrkabで表したときの係数とみなせる。

整数解を求める手順

  1. 互除法の操作を実行し、上記の表を埋める。vnを求める。
  2. vn=(x0,y0)とすると、ax0+by0=1が成り立つ。
  3. 一般解を求める。
    ax+by=1)     ax0+by0=1a(xx0)+b(yy0)=0
    定理1 より
    xx0=mb
    yy0=ma

よって一般解は整数mを用いて
   x=x0+mb
   y=y0ma
    
abの大小関係や正負によって、互除法の初期値とベクトルとの関係が変化するので注意

具体例

具体例として82x+23y=1の整数解を求める。
a=82b=23としてユークリッドの互除法を実行すると

互除法vabの式
82=233+13v1=(1,0)(0,1)3=(1,3)a3b=13
23=131+10v2=(0,1)(1,3)1=(1,4)a+4b=10
13=101+3v3=(1,3)(1,4)1=(2,7)2a7b=3
10=33+1v4=(1,4)(2,7)3=(7,25)7a+25b=1

上表より82x+23y=1の解の1つはx=7y=25
一般解はmを整数として
   x=7+23m
   y=2582m

実践してみると分かるが、ベクトルの計算に必要な情報は各ステップにおける商のみ。
vkを算出するための数式に登場するベクトルは前行を参照・転記すれば良いので
計算は割と簡単。

※途中で出てきたabの式を組み合わせて「a+b=」の形の式を新しく作ることができる。
互除法の途中で目的を達成できるときもあるので留意したい。

筆算(試作)

符号やらの関係でミスしがちなので、ミスを減らしつつコンパクトに計算する方法を考えたい。
とりあえず試作。
ax+by=1a(1,0)b(0,1)とおいたときに、
互除法の初期値s1s2をベクトルで表す。
s2から始めて「ベクトルに(1)×互除法の商をかける→1つ前のベクトルを加える」操作を繰り返す。

例:82x+23y=1
互除法の結果より
q:3,1,1,3
r:13,10,3,1

筆算 試作 筆算 試作
互除法のStep2の結果を使って
v2=(1,4)で、Step2のあまりが10であることから、
(x,y)=(1,4)は方程式82x+23y=10の整数解の一つである」
みたいなことがいえる。

おわりに

ax+by=1ならば
ax1(modb)
by1(moda)

よって今回の計算は、mod演算における逆数っぽいものを求める操作とみることもできそう。
その意味や応用についてはよく分かりませんが、そのうち考えてみたいと思います。

おまけ

計算用のpythonプログラム。 Jupyter Notebook などで実行できる。
最終行の数字を適当に変更して実行すると演習に役立つかも。

      import math
def euclidEx(a,b):
    g=math.gcd(a,b)
    if g>1:
        print('互いに素な数を入力してください')
        return
    if abs(a)<abs(b):
        tmp1=abs(b)
        tmp2=abs(a)
#a=[1,0]、b=[0,1]とおく
#tmp1に相当するベクトル: v1
        if(b<0):
            v1=[0,-1]
        else:
            v1=[0,1]
#tmp2に相当するベクトル
        if(a<0):
            v2=[-1,0]
        else:
            v2=[1,0]
    else:
        tmp1=abs(a)
        tmp2=abs(b)
#a=[1,0]、b=[0,1]とおく
#tmp1に相当するベクトル: v1
        if(a<0):
            v1=[-1,0]
        else:
            v1=[1,0]
#tmp2に相当するベクトル
        if(b<0):
            v2=[0,-1]
        else:
            v2=[0,1]
        
    s=''
    cnt=0
    while tmp2>1:
        q=tmp1//tmp2
        r=tmp1%tmp2
        v=[0,0]
        v[0]=v1[0]-v2[0]*q
        v[1]=v1[1]-v2[1]*q
        s=s+str(tmp1)+'='+str(tmp2)+' × '+str(q)+' + '+str(r)+'        \t'
        s=s+'v_'+str(cnt)+'=' +str(v1)+' - '+str(v2)+ ' ・ ' + str(q)+'\t= '+str(v)+'        \t'
        s=s+polynominal(v,['a','b'])+' = '+ str(r)
        s=s+'\n'
        
        tmp1=tmp2
        tmp2=r
        v1=list(v2)
        v2=list(v)
        
        cnt=cnt+1
        if cnt>100:
            break
    print(s)

def term(keisu,moji,isBegin):
#多項式の中の項を返す(符号、演算子を調整、係数が1のとき係数を削除)
    absK=abs(keisu)  #係数の絶対値
    if absK==1:
         absK=''
    else:
        absK=str(absK)
    if(keisu)>0:        #係数が正
        if isBegin==True:
            ope=''
            sgn=''
        else:
            ope=' + '
            sgn=''
        result=ope+sgn+absK+moji
    elif keisu<0:       #係数が負
        if isBegin==True:
            ope=''
            sgn='-'
        else:
            ope=' - '
            sgn=''
        result=ope+sgn+absK+moji
    else:               #係数が0
        result=''
    return result


def polynominal(k_lst,moji_lst):
#多項式を表す文字列を返す
    result=''
    for i in range(len(k_lst)):
        if i==0:
            result=result+term(k_lst[i],moji_lst[i],True)
        else:
            result=result+term(k_lst[i],moji_lst[i],False)
    return result

#例
euclidEx(131,17)

    
投稿日:20231013
OptHub AI Competition

この記事を高評価した人

高評価したユーザはいません

この記事に送られたバッジ

バッジはありません。
バッチを贈って投稿者を応援しよう

バッチを贈ると投稿者に現金やAmazonのギフトカードが還元されます。

投稿者

tanu
29
18224

コメント

他の人のコメント

コメントはありません。
読み込み中...
読み込み中
  1. ax+by=1の整数解
  2. はじめに
  3. 前提と表記
  4. ax+by=0の整数解
  5. ユークリッドの互除法(表)
  6. 具体例
  7. おわりに
  8. おまけ