Диофантово уравнение II порядка

Диофантово уравнение II порядка

       Диофантово уравнение второго порядка имеет вид:

a * x + b * y = c; a, b, c - известные, x, y - неизвестные

 

       Замечу, что зачастую нужно найти не просто какое-то решение, а:

● все решения

● количество решений или сами решения в определённом отрезке

● нахождение решений с наименьшей суммой неизвестных

 

Вырожденный случай

Один вырожденный случай мы сразу исключим из рассмотрения: когда a = b = 0. В этом случае, понятно, уравнение имеет либо бесконечно много произвольных решений, либо же не имеет решений вовсе (в зависимости от того, c = 0 или нет).

 

Нахождение одного решения

 

Найти одно из решений диофантова уравнения с двумя неизвестными можно с помощью Расширенного алгоритма Евклида. Предположим сначала, что числа a и b неотрицательны.

 

Расширенный алгоритм Евклида по заданным неотрицательным числам a и b находит их наибольший общий делитель g, а также такие коэффициенты x_g и y_g, что:

a * x_g + b * y_g = g.

 

Утверждается, что если c делится на g = gcd(a,b), то диофантово уравнение a * x + b * y = c имеет решение; в противном случае диофантово уравнение решений не имеет. Доказательство следует из очевидного факта, что линейная комбинация двух чисел по-прежнему должна делиться на их общий делитель.

 

Предположим, что c делится на g, тогда, очевидно, выполняется:

a * x_g * (c / g) + b * y_g * (c / g) = c

 

т. е. одним из решений диофантова уравнения являются числа:

x_0 = x_g * (c / g), y_0 = y_g

 

Мы описали решение в случае, когда числа a и b неотрицательны. Если же одно из них или они оба отрицательны, то можно поступить таким образом: взять их по модулю (абсолютное значение, а не модулярная арифметика) и применить к ним алгоритм Евклида, как было описано выше, а затем изменить знак найденных x_0 и y_0 в соответствии с настоящим знаком чисел a и b соответственно.

 

Реализация (напомним, здесь мы считаем, что входные данные a=b=0 недопустимы):

 

bool find_any_solution(int a, int b, int c, int & x0, int & y0, int & g) {        g = gcdex(abs(a), abs(b), x0, y0);        if (c % g!= 0)                    return false;        x0 *= c / g;        y0 *= c / g;        if (a < 0) x0 *= -1;        if (b < 0) y0 *= -1;        return true; }

 




double arrow
Сейчас читают про: