A lineal ecuación Diophantine en dos variables es una ecuación de la forma ax + by = c , donde un , b y c son números enteros constantes y x y y son enteros variables.
Para muchas ecuaciones naturales de Diophantine, x e y representan cantidades que no pueden ser negativas.
Tarea
Escribir un programa o función que acepta los coeficientes de un , b y c como entrada y devuelve un par arbitrario de números naturales (0, 1, 2, ...) x y y que verifican la ecuación ax + by = c , si un par tal existe
Reglas adicionales
Puede elegir cualquier formato para entrada y salida que involucre solo los enteros deseados y, opcionalmente, la notación de matriz / lista / matriz / tupla / vector de su idioma, siempre que no incruste ningún código en la entrada.
Puede suponer que los coeficientes a y b son ambos distintos de cero.
Su código debe funcionar para cualquier triplete de enteros entre -2 60 y 2 60 ; debe terminar en menos de un minuto en mi máquina (Intel i7-3770, 16 GiB RAM).
No puede utilizar ningún elemento integrado que resuelva las ecuaciones de Diophantine y, por lo tanto, trivialice esta tarea, como las de Mathematica
FindInstance
oFrobeniusSolve
.Su código puede comportarse como quiera si no se encuentra una solución, siempre que cumpla con el límite de tiempo y su salida no se pueda confundir con una solución válida.
Se aplican reglas estándar de código de golf .
Ejemplos
Los siguientes ejemplos ilustran E / S válidas para la ecuación 2x + 3y = 11 , que tiene exactamente dos soluciones válidas ( (x, y) = (4,1) y (x, y) = (1,3) ).
Input: 2 3 11 Output: [4 1] Input: (11 (2,3)) Output: [3],(1)
La única solución válida de 2x + 3y = 2 es el par (x, y) = (1,0) .
Los siguientes ejemplos ilustran E / S válidas para la ecuación 2x + 3y = 1 , que no tiene soluciones válidas .
Input: (2 3 1) Output: [] Input: 1 2 3 Output: -1 Input: [[2], [3], [1]] Output: (2, -1)
Para (a, b, c) = (1152921504606846883, -576460752303423433, 1) , todas las soluciones correctas (x, y) satisfacen que (x, y) = (135637824071393749 - bn, 271275648142787502 + an) para algún número entero no negativo n .
fuente
Respuestas:
Pyth, 92 bytes
Es todo un monstruo.
Pruébelo en línea: demostración . El formato de entrada es
c\n[a,b]
y el formato de salida es[x,y]
.En el caso de que no exista una solución entera, no imprimiré nada, y en el caso de que no exista una solución entera natural, simplemente imprimiré una solución entera aleatoria.
Explicación (descripción general)
Al principio, encontraré una solución entera para la ecuación
ax + by = gcd(a,b)
usando el algoritmo Euclidiano Extendido.Luego modificaré la solución (mi multiplicación
a
yb
conc/gcd(a,b)
) para obtener una solución entera deax + by = c
. Esto funciona, sic/gcd(a,b)
es un número entero. De lo contrario, no existe una solución.Todas las otras soluciones de enteros tienen la forma
a(x+n*b/d) + b(y-n*a/d) = c
cond = gcd(a,b)
for integern
. Usando las dos desigualdadesx+n*b/d >= 0
yy-n*a/d >= 0
puedo determinar 6 valores posibles paran
. Probaré los 6 e imprimiré la solución con el coeficiente más bajo más alto.Explicación (detallada)
El primer paso es encontrar una solución entera a la ecuación
ax' + by' = gcd(a,b)
. Esto se puede hacer usando el algoritmo euclidiano extendido. Puede hacerse una idea de cómo funciona en Wikipedia . La única diferencia es que, en lugar de usar 3 columnas (r_i s_i t_i
), usaré 6 columnas (r_i-1 r_i s_i-1 s_i t_i-1 t_i
). De esta manera no tengo que mantener las dos últimas filas en la memoria, solo la última.Ahora quiero encontrar una solución para
ax + by = c
. Esto solo es posible cuandoc mod gcd(a,b) == 0
. Si se satisface esta ecuación, simplemente multiplicox',y'
conc/gcd(a,b)
.Tenemos una solución entera para
ax + by = c
. Aviso, quex
,y
o ambos puede ser negativo. Por lo tanto, nuestro objetivo es transformarlos en no negativos.Lo bueno de las ecuaciones de diofantina es que podemos describir todas las soluciones usando solo una solución inicial. Si
(x,y)
es una solución, todas las demás soluciones tienen la forma(x-n*b/gcd(a,b),y+n*a/gcd(a,b))
den
entero.Por lo tanto, queremos encontrar un
n
, dondex-n*b/gcd(a,b) >= 0
yy+n*a/gcd(a,b >= 0
. Después de alguna transformación, terminamos con las dos desigualdadesn >= -x*gcd(a,b)/b
yn >= y*gcd(a,b)/a
. Observe que el símbolo de desigualdad podría mirar en la otra dirección debido a la división con un potencial negativoa
ob
. No me importa mucho, simplemente digo que un número de-x*gcd(a,b)/b - 1, -x*gcd(a,b)/b, -x*gcd(a,b)/b + 1
satisface definitivamente la desigualdad 1, y un número dey*gcd(a,b)/a - 1, y*gcd(a,b)/a, y*gcd(a,b)/a + 1
satisface la desigualdad 2. Si hay unn
, que satisface ambas desigualdades, uno de los 6 números también lo hace.Luego calculo las nuevas soluciones
(x-n*b/gcd(a,b),y+n*a/gcd(a,b))
para los 6 valores posibles den
. E imprimo la solución con el valor más bajo más alto.La ordenación por su orden ordenado funciona de la siguiente manera. Estoy usando el ejemplo
2x + 3y = 11
Ordeno cada una de las 6 soluciones (esto se llama claves), y clasifico las soluciones originales por sus claves:
Esto ordena una solución no negativa completa hasta el final (si hay alguna).
fuente
Matlab (660)
Explicación:
el código toma tres invariantes a, b, c como entrada, estos últimos se someten a un par de condiciones antes de proceder a calcular:
1- si (a + b> c) y (a, b, c> 0) no hay solución!
2- si (a + b <c), (a, b, c <0) no hay solución!
3- si (a, b) tienen signos opuestos comunes de c: ¡no hay solución!
4- si el dosificador GCD (a, b) divide c, ¡entonces no hay solución otra vez! , de lo contrario, divida todas las variantes por GCD.
después de esto, tenemos que verificar otra condición, debería facilitar y acortar el camino hacia la solución deseada.
5- si c divide a o b, solución s = (x o y) = (c- [ax, yb]) / [b, a] = C / [b, a] + [ax, yb] / [b , a] = S + [ax, yb] / [b, a] donde S es natural, por lo que ax / b o by / a tendrían soluciones directas no negativas que son respectivamente x = b o y = a. (observe que las soluciones pueden ser solo valores nulos en caso de que las soluciones arbitrarias anteriores se revelen negativas)
cuando el programa alcanza esta etapa, se barre un rango más estrecho de soluciones para x = (c-yb) / a, gracias a la congruencia, de barrer rangos más grandes de números, que se encuentran repetidamente en ciclos regulares. el campo de búsqueda más grande es [xa, x + a] donde a es el divisor.
INTENTALO
fuente
Axioma, 460 bytes
ungolf y alguna prueba
En las otras 'soluciones' posibles había un error porque intentaba guardar las soluciones infinitas en una Lista; ahora se impone el límite de 80 soluciones máximo
fuente