Решить в два этапа.
На этапе 1 вычислить описание набора {(x, y): x, y в Z и ax + by = K}, используя стандартные методы обработки Диофантовы уравнения .Пусть g = gcd (a, b);если g не делит K, нет решений.Вычислите g с помощью расширенного евклидового алгоритма , чтобы решить ax '+ by' = g, а также вычислите g;первое решение (х ', у') * К / г.Другие решения аддитивно связаны целыми числами, кратными (-b / g, a / g).
На этапе 2 вычисляют описание решений (x, y), которые могут быть достигнуты с помощью различных вариантов выбораμ я .Поскольку K ≥ 0, мы знаем, что y ≥ 1 является необходимым условием.Если n - переменная, то x ≥ 0 и y ≥ 1 - необходимое и достаточное условие (установите µ 0 = y - 1 и µ x = 1 и все другие µs для0).
Если n является параметром, то все немного сложнее.Используя результаты этапа 1, найдите решение (x, y) с x ≥ 0 и максимумом y (если такого решения нет, то K не выполнимо).Для этого решения проверьте, x / y ≤ n.
def egcd(A, B):
"""Returns a triple (gcd(A, B), s, t) such that s * A + t * B == gcd(A, B)."""
a, b, s, t, u, v = A, B, 1, 0, 0, 1
while True:
assert s * A + t * B == a
assert u * A + v * B == b
if not b:
break
q, r = divmod(a, b)
a, b, s, t, u, v = b, r, u, v, s - q * u, t - q * v
return a, s, t
def solvable(K, a, b):
g, s, t = egcd(a, b)
q, r = divmod(K, g)
if r:
return False
x, y = s * q, t * q
assert a * x + b * y == K
d = a // g
q, r = divmod(y, d)
if r <= 0:
q -= 1
r += d
assert 0 < r <= d
x, y = x + q * (b // g), r
assert a * x + b * y == K
return x >= y