Линейные диофантовы уравнения ax + by = c: когда есть решение и как найти все?
Нужно решить уравнение ax + by = c в целых числах (например, найти, можно ли набрать сумму c монетами номиналов через комбинацию). Когда решение существует и как получить общий вид всех решений? И как найти, например, неотрицательное или минимальное по x?
2 ответа
Уравнение ax + by = c имеет целочисленные решения тогда и только тогда, когда c делится на g = gcd(a, b). Это критерий из расширенного Евклида.
Алгоритм:
- Найди
g = gcd(a,b)и коэффициентыx0, y0:a·x0 + b·y0 = g(расширенный Евклид). - Если
c % g != 0→ решений нет. - Иначе домножь на
c/g: одно частное решениеx = x0·(c/g),y = y0·(c/g).
Общее решение (все целые решения):
x = x0·(c/g) + k·(b/g)
y = y0·(c/g) − k·(a/g)
для любого целого k.
bool solve_dio(long long a, long long b, long long c,
long long &x, long long &y, long long &g) {
long long x0, y0;
g = ext_gcd(abs(a), abs(b), x0, y0);
if (c % g != 0) return false;
x = x0 * (c / g);
y = y0 * (c / g);
if (a < 0) x = -x;
if (b < 0) y = -y;
return true;
}
Сложность — O(log min(a,b)). Чтобы найти, например, минимальное неотрицательное x, сдвигай k: шаг по x равен b/g, поэтому x = ((x % (b/g)) + (b/g)) % (b/g) даёт наименьший неотрицательный x, а соответствующий y пересчитывается. Будь аккуратен со знаками a, b.
Частая прикладная постановка — «сколько неотрицательных решений» (задача о монетах/числе Фробениуса). После нахождения общего вида ты ограничиваешь k двумя неравенствами x ≥ 0 и y ≥ 0, получаешь диапазон допустимых k и считаешь длину этого целочисленного отрезка. Главное — не перепутать направление неравенства при отрицательных a/g или b/g. Проверь руками на маленьком примере.