Skip to Content

Ecuación diofántica lineal

Una ecuación diofántica lineal (en dos variables) es una ecuación de la forma general:

ax+by=cax + by = c

donde aa, bb, cc son enteros dados, y xx, yy son enteros desconocidos.

En este artículo consideramos varios problemas clásicos sobre estas ecuaciones:

  • encontrar una solución
  • encontrar todas las soluciones
  • encontrar la cantidad de soluciones y las soluciones mismas en un intervalo dado
  • encontrar una solución con valor mínimo de x+yx + y

El caso degenerado

Un caso degenerado que hay que cuidar es cuando a=b=0a = b = 0. Es fácil ver que o no hay soluciones o hay infinitas, según si c=0c = 0 o no. En el resto de este artículo ignoramos este caso.

Solución analítica

Cuando a0a \neq 0 y b0b \neq 0, la ecuación ax+by=cax+by=c se puede tratar de forma equivalente como cualquiera de las siguientes:

axc(modb)byc(moda)\begin{align} ax &\equiv c \pmod b \ by &\equiv c \pmod a \end{align}

Sin pérdida de generalidad, supongamos que b0b \neq 0 y consideremos la primera ecuación. Cuando aa y bb son coprimos, la solución se da como

xca1(modb),x \equiv ca^{-1} \pmod b,

donde a1a^{-1} es el inverso modular de aa módulo bb.

Cuando aa y bb no son coprimos, los valores de axax módulo bb para todo entero xx son divisibles por g=gcd(a,b)g=\gcd(a, b), así que la solución solo existe cuando cc es divisible por gg. En este caso, una de las soluciones se puede encontrar reduciendo la ecuación por gg:

(a/g)x(c/g)(modb/g).(a/g) x \equiv (c/g) \pmod{b/g}.

Por definición de gg, los números a/ga/g y b/gb/g son coprimos, así que la solución se da explícitamente como

{x(c/g)(a/g)1(modb/g),y=caxb.{x(c/g)(a/g)1(modb/g),y=caxb.\begin{cases} x \equiv (c/g)(a/g)^{-1}\pmod{b/g},\ y = \frac{c-ax}{b}. \end{cases}

Solución algorítmica

El lema de Bézout (también llamado identidad de Bézout) es un resultado útil para entender la siguiente solución.

Sea g=gcd(a,b)g = \gcd(a,b). Entonces existen enteros x,yx,y tales que ax+by=gax + by = g.

Además, gg es el menor entero positivo que se puede escribir como ax+byax + by; todos los enteros de la forma ax+byax + by son múltiplos de gg.

Para encontrar una solución de la ecuación diofántica con 2 incógnitas, se puede usar el algoritmo de Euclides extendido. Primero, supongamos que aa y bb son no negativos. Cuando aplicamos el algoritmo de Euclides extendido a aa y bb, podemos encontrar su máximo común divisor gg y 2 números xgx_g e ygy_g tales que:

axg+byg=ga x_g + b y_g = g

Si cc es divisible por g=gcd(a,b)g = \gcd(a, b), entonces la ecuación diofántica dada tiene solución; si no, no tiene ninguna. La demostración es directa: una combinación lineal de dos números es divisible por su divisor común.

Ahora supongamos que cc es divisible por gg, entonces tenemos:

axgcg+bygcg=ca \cdot x_g \cdot \frac{c}{g} + b \cdot y_g \cdot \frac{c}{g} = c

Por lo tanto una de las soluciones de la ecuación diofántica es:

x0=xgcg,x_0 = x_g \cdot \frac{c}{g},

y0=ygcg.y_0 = y_g \cdot \frac{c}{g}.

La idea de arriba sigue funcionando cuando aa o bb o ambos son negativos. Solo hay que cambiar el signo de x0x_0 e y0y_0 cuando sea necesario.

Por último, podemos implementar esta idea así (nótese que este código no considera el caso a=b=0a = b = 0):

int gcd(int a, int b, int& x, int& y) { if (b == 0) { x = 1; y = 0; return a; } int x1, y1; int d = gcd(b, a % b, x1, y1); x = y1; y = x1 - y1 * (a / b); return d; } bool find_any_solution(int a, int b, int c, int &x0, int &y0, int &g) { g = gcd(abs(a), abs(b), x0, y0); if (c % g) { return false; } x0 *= c / g; y0 *= c / g; if (a < 0) x0 = -x0; if (b < 0) y0 = -y0; return true; }

Obtener todas las soluciones

A partir de una solución (x0,y0)(x_0, y_0), podemos obtener todas las soluciones de la ecuación dada.

Sea g=gcd(a,b)g = \gcd(a, b) y sean x0,y0x_0, y_0 enteros que satisfacen lo siguiente:

ax0+by0=ca \cdot x_0 + b \cdot y_0 = c

Ahora, deberíamos ver que sumar b/gb / g a x0x_0 y, al mismo tiempo, restar a/ga / g de y0y_0 no rompe la igualdad:

a(x0+bg)+b(y0ag)=ax0+by0+abgbag=ca \cdot \left(x_0 + \frac{b}{g}\right) + b \cdot \left(y_0 - \frac{a}{g}\right) = a \cdot x_0 + b \cdot y_0 + a \cdot \frac{b}{g} - b \cdot \frac{a}{g} = c

Obviamente, este proceso se puede repetir, así que todos los números de la forma:

x=x0+kbgx = x_0 + k \cdot \frac{b}{g}

y=y0kagy = y_0 - k \cdot \frac{a}{g}

son soluciones de la ecuación diofántica dada.

Como la ecuación es lineal, todas las soluciones yacen sobre la misma recta, y por definición de gg este es el conjunto de todas las soluciones posibles de la ecuación diofántica dada.

Encontrar la cantidad de soluciones y las soluciones en un intervalo dado

De la sección anterior debería quedar claro que si no imponemos restricciones sobre las soluciones, habría infinitas. Así que en esta sección añadimos restricciones sobre el intervalo de xx e yy, y vamos a intentar contar y enumerar todas las soluciones.

Sean dos intervalos: [minx;maxx][min_x; max_x] y [miny;maxy][min_y; max_y] y digamos que solo queremos encontrar las soluciones en estos dos intervalos.

Nótese que si aa o bb es 00, entonces el problema solo tiene una solución. No consideramos ese caso acá.

Primero, podemos encontrar una solución que tenga el valor mínimo de xx tal que xminxx \ge min_x. Para esto, primero encontramos cualquier solución de la ecuación diofántica. Después, desplazamos esta solución para obtener xminxx \ge min_x (usando lo que sabemos del conjunto de todas las soluciones en la sección anterior). Esto se puede hacer en O(1)O(1). Denotemos este valor mínimo de xx por lx1l_{x1}.

De forma similar, podemos encontrar el valor máximo de xx que satisface xmaxxx \le max_x. Denotemos este valor máximo de xx por rx1r_{x1}.

De forma similar, podemos encontrar el valor mínimo de yy (yminy)(y \ge min_y) y el valor máximo de yy (ymaxy)(y \le max_y). Denotemos los valores correspondientes de xx por lx2l_{x2} y rx2r_{x2}.

La solución final son todas las soluciones con xx en la intersección de [lx1,rx1][l_{x1}, r_{x1}] y [lx2,rx2][l_{x2}, r_{x2}]. Denotemos esta intersección por [lx,rx][l_x, r_x].

A continuación está el código que implementa esta idea. Nótese que dividimos aa y bb al principio por gg. Como la ecuación ax+by=ca x + b y = c es equivalente a agx+bgy=cg\frac{a}{g} x + \frac{b}{g} y = \frac{c}{g}, podemos usar esta última y tener gcd(ag,bg)=1\gcd(\frac{a}{g}, \frac{b}{g}) = 1, lo que simplifica las fórmulas.

void shift_solution(int & x, int & y, int a, int b, int cnt) { x += cnt * b; y -= cnt * a; } int find_all_solutions(int a, int b, int c, int minx, int maxx, int miny, int maxy) { int x, y, g; if (!find_any_solution(a, b, c, x, y, g)) return 0; a /= g; b /= g; int sign_a = a > 0 ? +1 : -1; int sign_b = b > 0 ? +1 : -1; shift_solution(x, y, a, b, (minx - x) / b); if (x < minx) shift_solution(x, y, a, b, sign_b); if (x > maxx) return 0; int lx1 = x; shift_solution(x, y, a, b, (maxx - x) / b); if (x > maxx) shift_solution(x, y, a, b, -sign_b); int rx1 = x; shift_solution(x, y, a, b, -(miny - y) / a); if (y < miny) shift_solution(x, y, a, b, -sign_a); if (y > maxy) return 0; int lx2 = x; shift_solution(x, y, a, b, -(maxy - y) / a); if (y > maxy) shift_solution(x, y, a, b, sign_a); int rx2 = x; if (lx2 > rx2) swap(lx2, rx2); int lx = max(lx1, lx2); int rx = min(rx1, rx2); if (lx > rx) return 0; return (rx - lx) / abs(b) + 1; }

Una vez que tenemos lxl_x y rxr_x, también es simple enumerar todas las soluciones. Solo hay que iterar sobre x=lx+kbgx = l_x + k \cdot \frac{b}{g} para todo k0k \ge 0 hasta x=rxx = r_x, y encontrar los valores de yy correspondientes usando la ecuación ax+by=ca x + b y = c.

Encontrar la solución con valor mínimo de x+yx + y { data-toc-label=‘Find the solution with minimum value of ’ }

Acá, xx e yy también necesitan alguna restricción; si no, la respuesta puede volverse menos infinito.

La idea es similar a la sección anterior: encontramos cualquier solución de la ecuación diofántica, y después desplazamos la solución para satisfacer algunas condiciones.

Por último, usamos el conocimiento del conjunto de todas las soluciones para encontrar el mínimo:

x=x+kbg,x’ = x + k \cdot \frac{b}{g},

y=ykag.y’ = y - k \cdot \frac{a}{g}.

Nótese que x+yx + y cambia así:

x+y=x+y+k(bgag)=x+y+kbagx’ + y’ = x + y + k \cdot \left(\frac{b}{g} - \frac{a}{g}\right) = x + y + k \cdot \frac{b-a}{g}

Si a<ba < b, hay que elegir el menor valor posible de kk. Si a>ba > b, hay que elegir el mayor valor posible de kk. Si a=ba = b, todas las soluciones tendrán la misma suma x+yx + y.

Problemas de práctica