Bình thường, 92 byte
I!%vzhK%2u?sm,ed-hd*ed/F<G2cG2@G1G+~Q,hQ_eQj9 2)J*L/vzhKtKeoSNm-VJ/RhK_*LdQsm+LdtM3/V*LhK_JQ
Nó khá là quái vật.
Dùng thử trực tuyến: Trình diễn . Định dạng đầu vào là c\n[a,b]
và định dạng đầu ra là [x,y]
.
Trong trường hợp không có giải pháp số nguyên nào tồn tại, tôi sẽ không in gì cả và trong trường hợp không có giải pháp số nguyên tự nhiên nào tồn tại, tôi chỉ cần in một giải pháp số nguyên ngẫu nhiên.
Giải thích (Tổng quan thô)
Đầu tiên tôi sẽ tìm một giải pháp số nguyên cho phương trình ax + by = gcd(a,b)
bằng cách sử dụng thuật toán Euclide mở rộng.
Sau đó, tôi sẽ sửa đổi giải pháp (nhân a
và b
với c/gcd(a,b)
) để có được một giải pháp số nguyên ax + by = c
. Điều này hoạt động, nếu c/gcd(a,b)
là một số nguyên. Nếu không thì không tồn tại một giải pháp.
Tất cả các giải pháp số nguyên khác có dạng a(x+n*b/d) + b(y-n*a/d) = c
với d = gcd(a,b)
số nguyên n
. Sử dụng hai bất đẳng thức x+n*b/d >= 0
và y-n*a/d >= 0
tôi có thể xác định 6 giá trị có thể cho n
. Tôi sẽ thử tất cả 6 trong số chúng và in giải pháp với hệ số thấp nhất cao nhất.
Giải thích (Chi tiết)
Bước đầu tiên là tìm một giải pháp số nguyên cho phương trình ax' + by' = gcd(a,b)
. Điều này có thể được thực hiện bằng cách sử dụng thuật toán Euclide mở rộng. Bạn có thể có một ý tưởng về cách nó hoạt động tại Wikipedia . Sự khác biệt duy nhất là, thay vì sử dụng 3 cột ( r_i s_i t_i
) tôi sẽ sử dụng 6 cột ( r_i-1 r_i s_i-1 s_i t_i-1 t_i
). Bằng cách này, tôi không phải giữ hai hàng cuối cùng trong bộ nhớ, chỉ có hàng cuối cùng.
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.
Bây giờ tôi muốn tìm một giải pháp để ax + by = c
. Điều này chỉ có thể, khi c mod gcd(a,b) == 0
. Nếu phương trình này được thỏa mãn, tôi chỉ cần nhân x',y'
với 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]
Chúng tôi có một giải pháp số nguyên cho ax + by = c
. Lưu ý rằng x
, y
hoặc cả hai có thể là tiêu cực. Vì vậy, mục tiêu của chúng tôi là biến đổi những thứ này thành không tiêu cực.
Điều hay ho về phương trình Diophantine là, chúng ta có thể mô tả tất cả các giải pháp chỉ bằng một giải pháp ban đầu. Nếu (x,y)
là một giải pháp, tất cả các giải pháp khác đều có dạng (x-n*b/gcd(a,b),y+n*a/gcd(a,b))
cho n
số nguyên.
Vì vậy, chúng tôi muốn tìm một n
, ở đâu x-n*b/gcd(a,b) >= 0
và y+n*a/gcd(a,b >= 0
. Sau một số biến đổi, chúng tôi kết thúc với hai bất đẳng thức n >= -x*gcd(a,b)/b
và n >= y*gcd(a,b)/a
. Lưu ý rằng biểu tượng bất bình đẳng có thể nhìn theo hướng khác do sự phân chia có tiềm năng a
hoặc b
. Tôi không quan tâm nhiều đến điều đó, tôi chỉ đơn giản nói rằng một số -x*gcd(a,b)/b - 1, -x*gcd(a,b)/b, -x*gcd(a,b)/b + 1
bất đẳng thức thỏa mãn bất đẳng thức 1 và một số y*gcd(a,b)/a - 1, y*gcd(a,b)/a, y*gcd(a,b)/a + 1
bất đẳng thức thỏa mãn 2. Có một n
, thỏa mãn cả hai bất đẳng thức, một trong 6 số cũng có.
Sau đó, tôi tính toán các giải pháp mới (x-n*b/gcd(a,b),y+n*a/gcd(a,b))
cho tất cả 6 giá trị có thể có n
. Và tôi in giải pháp với giá trị thấp nhất cao nhất.
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
Việc sắp xếp theo thứ tự sắp xếp của họ hoạt động theo cách sau. Tôi đang sử dụng ví dụ2x + 3y = 11
Tôi sắp xếp từng trong số 6 giải pháp (đây được gọi là khóa) và sắp xếp các giải pháp ban đầu theo các khóa của chúng:
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]
Điều này sắp xếp một giải pháp hoàn toàn không tiêu cực đến cùng (nếu có).