Линейное диофантово уравнение с двумя переменными - это уравнение вида ax + by = c , где a , b и c - постоянные целые числа, а x и y - целочисленные переменные.
Для многих естественных диофантовых уравнений x и y представляют величины, которые не могут быть отрицательными.
задача
Напишите программу или функцию, которая принимает коэффициенты a , b и c в качестве входных данных и возвращает произвольную пару натуральных чисел (0, 1, 2,…) x и y, которые проверяют уравнение ax + by = c , если такая пара существуют.
Дополнительные правила
Вы можете выбрать любой формат для ввода и вывода, который включает только нужные целые числа и, необязательно, массив / список / матрицу / кортеж / векторную нотацию вашего языка, если вы не вставляете какой-либо код во входные данные.
Вы можете предположить, что коэффициенты a и b не равны нулю.
Ваш код должен работать для любой тройки целых чисел от -2 60 до 2 60 ; он должен завершиться менее чем за минуту на моей машине (Intel i7-3770, 16 ГБ ОЗУ).
Вы не можете использовать любые встроенные модули, которые решают диофантовы уравнения и, таким образом, упрощают эту задачу, такие как Mathematica
FindInstance
илиFrobeniusSolve
.Ваш код может вести себя так, как вы хотите, если решение не может быть найдено, если оно соответствует ограничению по времени и его вывод не может быть перепутан с допустимым решением.
Применяются стандартные правила игры в гольф .
Примеры
Приведенные ниже примеры иллюстрируют действительный ввод / вывод для уравнения 2x + 3y = 11 , которое имеет ровно два действительных решения ( (x, y) = (4,1) и (x, y) = (1,3) ).
Input: 2 3 11 Output: [4 1] Input: (11 (2,3)) Output: [3],(1)
Единственным верным решением 2x + 3y = 2 является пара (x, y) = (1,0) .
Приведенные ниже примеры иллюстрируют действительный ввод / вывод для уравнения 2x + 3y = 1 , которое не имеет действительных решений .
Input: (2 3 1) Output: [] Input: 1 2 3 Output: -1 Input: [[2], [3], [1]] Output: (2, -1)
Для (a, b, c) = (1152921504606846883, -576460752303423433, 1) все правильные решения (x, y) удовлетворяют тому, что (x, y) = (135637824071393749 - bn, 271275648142787502 + an) для некоторого неотрицательного целого числа n ,
источник
Ответы:
Pyth, 92 байта
Это довольно монстр.
Попробуйте онлайн: Демонстрация . Формат ввода
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)
целым числомn
. Используя два неравенстваx+n*b/d >= 0
иy-n*a/d >= 0
я могу определить , 6 возможных значенийn
. Я попробую все 6 из них и распечатаю решение с самым высоким наименьшим коэффициентом.Пояснение (подробно)
Первый шаг - найти целочисленное решение уравнения
ax' + by' = gcd(a,b)
. Это можно сделать с помощью расширенного евклидова алгоритма. Вы можете получить представление о том, как это работает в Википедии . Разница лишь в том, что вместо использования 3 columns (r_i s_i t_i
) я буду использовать 6 columns (r_i-1 r_i s_i-1 s_i t_i-1 t_i
). Таким образом, мне не нужно хранить последние две строки в памяти, только последнюю.Теперь я хочу найти решение
ax + by = c
. Это возможно только тогда, когдаc mod gcd(a,b) == 0
. Если это уравнение выполнено, я просто умножаюсьx',y'
наc/gcd(a,b)
.У нас есть целочисленное решение для
ax + by = c
. Обратите внимание, чтоx
,y
или оба могут быть отрицательными. Поэтому наша цель - преобразовать их в неотрицательные.Хорошая вещь о диофантовых уравнениях состоит в том, что мы можем описать все решения, используя только одно начальное решение. Если
(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
. После некоторого преобразования мы получаем два неравенства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. Если есть an
, которое удовлетворяет обоим неравенствам, одно из 6 чисел также делает.Затем я рассчитываю новые решения
(x-n*b/gcd(a,b),y+n*a/gcd(a,b))
для всех 6 возможных значенийn
. И я печатаю решение с самым высоким наименьшим значением.Сортировка по порядку сортировки работает следующим образом. Я использую пример
2x + 3y = 11
Я сортирую каждое из 6 решений (это называется ключами) и сортирую исходные решения по ключам:
Это сортирует полное неотрицательное решение до конца (если есть).
источник
Матлаб (660)
Объяснение:
код принимает в качестве входных данных три инварианта a, b, c, эти последние подчиняются паре условий перед тем, как продолжить вычисление:
1 - если (a + b> c) и (a, b, c> 0) нет решения!
2- если (a + b <c), (a, b, c <0) нет решения!
3 - если (a, b) имеют общие противоположные признаки c: нет решения!
4 - если GCD (a, b) не делится на c, то снова нет решения! иначе делим все варианты по GCD.
после этого мы должны проверить другое условие, оно должно облегчить и сократить путь к желаемому решению.
5- если c разделить a или b, решение s = (x или y) = (c- [ax, yb]) / [b, a] = C / [b, a] + [ax, yb] / [b , a] = S + [ax, yb] / [b, a], где S является естественным, поэтому у ax / b или / a будут впредь неотрицательные прямые решения, которые соответственно x = b или y = a. (обратите внимание, что решения могут быть просто нулевыми значениями в случае, если предыдущие произвольные решения выявлены как отрицательные)
когда программа достигает этой стадии, более узкий диапазон решений для x = (c-yb) / a вместо этого, благодаря конгруэнтности, охватывается большими диапазонами чисел, которые периодически повторяются регулярными циклами. самое большое поле поиска - [xa, x + a], где a - делитель.
ПОПЫТАЙСЯ
источник
Аксиома, 460 байт
негольф и какой-то тест
В других возможных «решениях» была ошибка, потому что она пыталась сохранить бесконечные решения в одном Списке; теперь наложено ограничение в 80 решений макс
источник