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
用c/gcd(a,b)
),以获得的整数解ax + by = c
。如果c/gcd(a,b)
为整数,则此方法有效。否则,不存在解决方案。
所有其他整数解决方案均a(x+n*b/d) + b(y-n*a/d) = c
具有d = gcd(a,b)
for integer 的形式n
。使用这两个不等式x+n*b/d >= 0
,y-n*a/d >= 0
我可以确定的6个可能值n
。我将尝试所有6种方法,并以最高的最低系数打印解决方案。
说明(详细)
第一步是找到方程的整数解ax' + by' = gcd(a,b)
。这可以通过使用扩展的欧几里得算法来完成。您可以在Wikipedia上了解其工作原理。唯一的区别是,r_i s_i t_i
我将使用6列(r_i-1 r_i s_i-1 s_i t_i-1 t_i
)而不是3 列()。这样,我不必将最后两行保留在内存中,只需保留最后一行。
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方程的好处是,我们可以仅使用一个初始解来描述所有解。如果(x,y)
是一个解决方案,所有其他解决方案的形式是(x-n*b/gcd(a,b),y+n*a/gcd(a,b))
为n
整数。
因此,我们要查找a n
,where x-n*b/gcd(a,b) >= 0
和y+n*a/gcd(a,b >= 0
。经过一些转换,我们最终得到两个不等式n >= -x*gcd(a,b)/b
和n >= y*gcd(a,b)/a
。请注意,不等式符号可能会朝另一个方向看,这是因为被潜在的负数a
或所除b
。我对此并不在乎,我只是简单地说一个数字确实-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
满足不等式2。有一个n
满足两个不等式,6个数字之一也满足。
然后,我(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]
这样可以将一个完整的非负解决方案排序到最后(如果有)。