Pyth、92バイト
I!%vzhK%2u?sm,ed-hd*ed/F<G2cG2@G1G+~Q,hQ_eQj9 2)J*L/vzhKtKeoSNm-VJ/RhK_*LdQsm+LdtM3/V*LhK_JQ
それは非常に怪物です。
オンラインで試してください:デモンストレーション。入力形式はc\n[a,b]
で、出力形式は[x,y]
です。
整数解が存在しない場合は何も出力せず、自然整数解が存在しない場合は単純にランダムな整数解を出力します。
説明(大まかな概要)
最初にax + by = gcd(a,b)
、拡張ユークリッドアルゴリズムを使用して、方程式の整数解を見つけます。
次に、解(私の乗算a
とb
with c/gcd(a,b)
)を変更して、の整数解を取得しax + by = c
ます。c/gcd(a,b)
整数の場合、これは機能します。そうでなければ、解決策は存在しません。
他のすべての整数解は、for integerの形式a(x+n*b/d) + b(y-n*a/d) = c
を持ちます。2つの不等式を使用し、私は6つの可能な値を決定することができます。6つすべてを試して、最も低い係数でソリューションを印刷します。d = gcd(a,b)
n
x+n*b/d >= 0
y-n*a/d >= 0
n
説明(詳細)
最初のステップは、方程式の整数解を見つけることax' + by' = gcd(a,b)
です。これは、拡張ユークリッドアルゴリズムを使用して実行できます。Wikipediaでどのように機能するかについてのアイデアを得ることができます。唯一の違いは、3列(r_i s_i t_i
)を使用する代わりに、6列(r_i-1 r_i s_i-1 s_i t_i-1 t_i
)を使用することです。この方法では、最後の2行をメモリに保持する必要はなく、最後の1行のみを保持します。
K%2u?sm,ed-hd*ed/F<G2cG2@G1G+~Q,hQ_eQj9 2) implicit: Q = [a,b] (from input)
j9 2 convert 9 to base 2: [1,0,0,1]
+ Q add to Q => [a,b,1,0,0,1]
this is the initial row
u ) start with G = ^ and update G repeatedly
by the following expression, until
the value of G doesn't change anymore
? @G1 if G[1] != 0:
cG2 split G into parts of 2
m map the parts d to:
, the pair
ed d[1]
-hd*ed/F<G2 d[0]-d[1]*G[0]/G[1]
s unfold
else:
G G (don't change it, stop criterion for u)
%2 take every second element
we get the list [gcd(a,b),x',y']
K store this list in K
~Q,hQ_eQ afterwards change Q to [Q[0],-Q[1]] = [a,-b]
This will be important for the other parts.
今、私は解決策を見つけたいですax + by = c
。これはの場合にのみ可能c mod gcd(a,b) == 0
です。この式が満たされている場合、単純にと乗算x',y'
しc/gcd(a,b)
ます。
I!%vzhK...J*L/vzhKtK implicit: z = c in string format (from input)
%vzhK evaluated(z) mod K[0] (=gcd(a,b))
I! if not ^ than:
/vzhK c/K[0]
*L tK multipy ^ to each element in K[1:] (=[x',y'])
J and store the result in J, this is now [x,y]
の整数解がありax + by = c
ます。x
、y
またはその両方が負になる場合があることに注意してください。したがって、私たちの目標は、これらを非負に変換することです。
Diophantine方程式の良いところは、1つの初期解のみを使用してすべての解を記述できることです。(x,y)
が解である場合、他のすべての解は整数の形式(x-n*b/gcd(a,b),y+n*a/gcd(a,b))
ですn
。
そこで我々は、見つけたいn
、どこx-n*b/gcd(a,b) >= 0
とy+n*a/gcd(a,b >= 0
。いくつかの変換後、2つの不等式n >= -x*gcd(a,b)/b
とになりn >= y*gcd(a,b)/a
ます。不等式記号は、潜在的な負a
またはの除算のために他の方向を向く場合があることに注意してくださいb
。私はそれについてあまり気にしません、私は単に1つの数が間違いなく-x*gcd(a,b)/b - 1, -x*gcd(a,b)/b, -x*gcd(a,b)/b + 1
不等式1をy*gcd(a,b)/a - 1, y*gcd(a,b)/a, y*gcd(a,b)/a + 1
満たし、1つの数が不等式2 を満たしていると単純に言いn
ます。
次に、(x-n*b/gcd(a,b),y+n*a/gcd(a,b))
可能な6つの値すべてに対して新しい解を計算しますn
。そして、私は最高の最低値でソリューションを印刷します。
eoSNm-VJ/RhK_*LdQsm+LdtM3/V*LhK_JQ
_J reverse J => [y,x]
*LhK multiply each value with K[0] => [y*gcd,x*gcd]
/V Q vectorized division => [y*gcd/a,-x*gcd/b]
m map each d of ^ to:
tM3 [-1,0,1]
+Ld add d to each ^
s unfold
these are the possible values for n
m map each d (actually n) of ^ to:
*LdQ multiply d to Q => [a*n,-b*n]
_ reverse => [-b*n,a*n]
/RhK divide by K[0] => [-b*n/gcd,a*n/gcd]
-VJ vectorized subtraction with J
=> [x+b*n/gcd,y-a*n/gcd]
oSN order the solutions by their sorted order
e print the last one
ソート順によるソートは、次のように機能します。私は例を使用しています2x + 3y = 11
6つのソリューション(これはキーと呼ばれます)をそれぞれソートし、元のソリューションをキーでソートします。
solutions: [1, 3], [4, 1], [7, -1], [-5, 7], [-2, 5], [1, 3]
keys: [1, 3], [1, 4], [-1, 7], [-5, 7], [-2, 5], [1, 3]
sort by key:
solutions: [-5, 7], [-2, 5], [7, -1], [1, 3], [1, 3], [4, 1]
keys: [-5, 7], [-2, 5], [-1, 7], [1, 3], [1, 3], [1, 4]
これにより、完全な非負の解が最後にソートされます(ある場合)。