Pyth, 92 bayt
I!%vzhK%2u?sm,ed-hd*ed/F<G2cG2@G1G+~Q,hQ_eQj9 2)J*L/vzhKtKeoSNm-VJ/RhK_*LdQsm+LdtM3/V*LhK_JQ
Oldukça canavar.
Çevrimiçi deneyin: Gösteri . Girdi biçimi c\n[a,b]
ve çıktı biçimi [x,y]
.
Tamsayı çözümünün olmaması durumunda, hiçbir şey yazdırmayacağım ve doğal tamsayı çözümünün olmaması durumunda, rastgele bir tamsayı çözümü basacağım.
Açıklama (Genel Bakış)
İlk önce ax + by = gcd(a,b)
Genişletilmiş Öklid algoritmasını kullanarak denkleme tamsayı bir çözüm bulacağım .
Sonra bir tamsayı çözümü elde etmek için çözümü (benim çarpma a
ve b
ile c/gcd(a,b)
) değiştireceğim ax + by = c
. Bu c/gcd(a,b)
bir tamsayı ise çalışır . Aksi takdirde bir çözüm yoktur.
Diğer tüm tamsayı çözeltiler formuna sahip a(x+n*b/d) + b(y-n*a/d) = c
olan d = gcd(a,b)
tamsayı n
. İki eşitsizlikleri kullanma x+n*b/d >= 0
ve y-n*a/d >= 0
ben 6 olası değerleri belirleyebilir n
. 6 tanesinin hepsini deneyeceğim ve çözümü en düşük katsayılı yazdıracağım.
Açıklama (Ayrıntılı)
İlk adım, denkleme tamsayı bir çözüm bulmaktır ax' + by' = gcd(a,b)
. Bu, genişletilmiş Öklid algoritması kullanılarak yapılabilir. Wikipedia'da nasıl çalıştığı hakkında bir fikir edinebilirsiniz . Tek fark, 3 sütun ( r_i s_i t_i
) kullanmak yerine 6 sütun ( r_i-1 r_i s_i-1 s_i t_i-1 t_i
) kullanacağım . Bu şekilde son iki satırı bellekte tutmak zorunda değilim, sadece son satırı.
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.
Şimdi bir çözüm bulmak istiyorum ax + by = c
. Bu sadece ne zaman mümkündür c mod gcd(a,b) == 0
. Bu denklem tatmin olmuşsa, ben sadece çarparak x',y'
ile 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]
İçin bir tamsayı çözümümüz var ax + by = c
. Bildirim, o x
, y
ya da her ikisi negatif olabilir. Yani amacımız bunları negatif olmayan biçime dönüştürmektir.
Diophantine denklemleri ile ilgili güzel bir şey, tüm çözümü sadece bir başlangıç çözümü kullanarak tanımlayabilmemizdir. Eğer (x,y)
diğer tüm çözümler formu olduğu, bir çözüm (x-n*b/gcd(a,b),y+n*a/gcd(a,b))
için n
bir tamsayı.
Bu nedenle bir n
, nerede x-n*b/gcd(a,b) >= 0
ve bulmak istiyoruz y+n*a/gcd(a,b >= 0
. Bazı dönüşüm sonra iki eşitsizlikler ile bitirmek n >= -x*gcd(a,b)/b
ve n >= y*gcd(a,b)/a
. Eşitsizlik simgesinin, potansiyel negatif a
veya ile bölünme nedeniyle diğer yöne bakabileceğine dikkat edin b
. Ben sadece söylemek, bu konuda o kadar umurumda değil ki biri sayısının -x*gcd(a,b)/b - 1, -x*gcd(a,b)/b, -x*gcd(a,b)/b + 1
1 eşitsizlik kesinlikle tatmin ve biri sayısının y*gcd(a,b)/a - 1, y*gcd(a,b)/a, y*gcd(a,b)/a + 1
bir olduğu 2. eşitsizlik tatmin n
tatmin her iki eşitsizlikler, 6 rakamlarından birini de yaptığı,.
Sonra (x-n*b/gcd(a,b),y+n*a/gcd(a,b))
6 olası değerin tümü için yeni çözümler hesaplıyorum n
. Ve çözümü en düşük değere sahip olarak yazdırıyorum.
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
Sıralama düzenine göre sıralama şu şekilde çalışır. Örneği kullanıyorum2x + 3y = 11
6 çözümün her birini sıralıyorum (buna anahtar denir) ve orijinal çözümleri anahtarlarına göre sıralıyorum:
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]
Bu, sonuna kadar negatif olmayan tam bir çözümü sıralar (varsa).