Une équation diophantienne linéaire à deux variables est une équation de la forme ax + par = c , où a , b et c sont des entiers constants et x et y sont des variables entières.
Pour de nombreuses équations diophantiennes naturelles, x et y représentent des quantités qui ne peuvent pas être négatives.
Tâche
Écrivez un programme ou une fonction qui accepte les coefficients a , b et c en entrée et renvoie une paire arbitraire de nombres naturels (0, 1, 2,…) x et y qui vérifient l'équation ax + by = c , si une telle paire existe.
Règles supplémentaires
Vous pouvez choisir n'importe quel format d'entrée et de sortie qui n'implique que les entiers souhaités et, éventuellement, la notation tableau / liste / matrice / tuple / vecteur de votre langue, tant que vous n'incorporez aucun code dans l'entrée.
Vous pouvez supposer que les coefficients a et b sont tous deux non nuls.
Votre code doit fonctionner pour tout triplet d'entiers compris entre -2 60 et 2 60 ; il doit se terminer en moins d'une minute sur ma machine (Intel i7-3770, 16 Go de RAM).
Vous ne pouvez pas utiliser de modules intégrés qui résolvent les équations diophantiennes et banalisent ainsi cette tâche, comme Mathematica
FindInstance
ouFrobeniusSolve
.Votre code peut se comporter comme vous le souhaitez si aucune solution ne peut être trouvée, tant qu'il respecte le délai et que sa sortie ne peut pas être confondue avec une solution valide.
Les règles de code-golf standard s'appliquent.
Exemples
Les exemples ci-dessous illustrent des E / S valides pour l'équation 2x + 3y = 11 , qui a exactement deux solutions valides ( (x, y) = (4,1) et (x, y) = (1,3) ).
Input: 2 3 11 Output: [4 1] Input: (11 (2,3)) Output: [3],(1)
La seule solution valable de 2x + 3y = 2 est la paire (x, y) = (1,0) .
Les exemples ci-dessous illustrent des E / S valides pour l'équation 2x + 3y = 1 , qui n'a pas de solutions valides .
Input: (2 3 1) Output: [] Input: 1 2 3 Output: -1 Input: [[2], [3], [1]] Output: (2, -1)
Pour (a, b, c) = (1152921504606846883, -576460752303423433, 1) , toutes les solutions correctes (x, y) satisfont que (x, y) = (135637824071393749 - bn, 271275648142787502 + an) pour un entier non négatif n .
la source
Réponses:
Pyth, 92 octets
C'est tout à fait un monstre.
Essayez-le en ligne: démonstration . Le format d'entrée est
c\n[a,b]
et le format de sortie est[x,y]
.Dans le cas où aucune solution entière n'existe, je n'imprimerai rien, et dans le cas où aucune solution entière naturelle n'existe, j'imprimerai simplement une solution entière aléatoire.
Explication (aperçu approximatif)
Dans un premier temps, je vais trouver une solution entière à l'équation
ax + by = gcd(a,b)
en utilisant l'algorithme euclidien étendu.Ensuite, je vais modifier la solution (ma multiplication
a
etb
avecc/gcd(a,b)
) pour obtenir une solution entière deax + by = c
. Cela fonctionne, sic/gcd(a,b)
est un entier. Sinon, il n'existe pas de solution.Toutes les autres solutions entières ont la forme
a(x+n*b/d) + b(y-n*a/d) = c
avecd = gcd(a,b)
for integern
. En utilisant les deux inégalitésx+n*b/d >= 0
ety-n*a/d >= 0
je peux déterminer 6 valeurs possibles pourn
. Je vais essayer les 6 et imprimer la solution avec le coefficient le plus bas le plus élevé.Explication (détaillée)
La première étape consiste à trouver une solution entière à l'équation
ax' + by' = gcd(a,b)
. Cela peut être fait en utilisant l'algorithme euclidien étendu. Vous pouvez vous faire une idée de son fonctionnement sur Wikipedia . La seule différence est qu'au lieu d'utiliser 3 colonnes (r_i s_i t_i
), j'utiliserai 6 colonnes (r_i-1 r_i s_i-1 s_i t_i-1 t_i
). De cette façon, je n'ai pas à garder les deux dernières lignes en mémoire, seulement la dernière.Maintenant, je veux trouver une solution
ax + by = c
. Cela n'est possible que lorsquec mod gcd(a,b) == 0
. Si cette équation est satisfaite, je multiplie simplementx',y'
avecc/gcd(a,b)
.Nous avons une solution entière pour
ax + by = c
. Notez quex
,y
ou les deux peuvent être négatifs. Notre objectif est donc de les transformer en non-négatifs.La bonne chose à propos des équations diophantiennes est que nous pouvons décrire toutes les solutions en utilisant une seule solution initiale. Si
(x,y)
est une solution, que toutes les autres solutions sont de la forme(x-n*b/gcd(a,b),y+n*a/gcd(a,b))
pourn
entier.Par conséquent, nous voulons trouver un
n
, oùx-n*b/gcd(a,b) >= 0
ety+n*a/gcd(a,b >= 0
. Après une certaine transformation, nous nous retrouvons avec les deux inégalitésn >= -x*gcd(a,b)/b
etn >= y*gcd(a,b)/a
. Notez que le symbole d'inégalité peut regarder dans l'autre sens en raison de la division avec un potentiel négatifa
oub
. Je m'en fiche pas mal, je dis simplement qu'un nombre de-x*gcd(a,b)/b - 1, -x*gcd(a,b)/b, -x*gcd(a,b)/b + 1
satisfait définitivement l'inégalité 1, et un nombre dey*gcd(a,b)/a - 1, y*gcd(a,b)/a, y*gcd(a,b)/a + 1
satisfait l'inégalité 2. Il y a unn
, qui satisfait les deux inégalités, l'un des 6 chiffres aussi.Ensuite, je calcule les nouvelles solutions
(x-n*b/gcd(a,b),y+n*a/gcd(a,b))
pour les 6 valeurs possibles den
. Et j'imprime la solution avec la valeur la plus basse la plus élevée.Le tri par leur ordre de tri fonctionne de la manière suivante. J'utilise l'exemple
2x + 3y = 11
Je trie chacune des 6 solutions (ce sont les clés) et trie les solutions originales par leurs clés:
Cela trie une solution non négative complète à la fin (le cas échéant).
la source
Matlab (660)
Explication:
le code prend en entrée trois invariants a, b, c, ces derniers sont soumis à quelques conditions avant de procéder au calcul:
1- si (a + b> c) et (a, b, c> 0) pas de solution!
2- si (a + b <c), (a, b, c <0) pas de solution!
3- si (a, b) ont des signes opposés communs de c: pas de solution!
4- Si GCD (a, b) ne divise pas c, alors plus de solution! sinon, divisez toutes les variantes par GCD.
après cela, nous devons vérifier une autre condition, elle devrait faciliter et raccourcir le chemin vers la solution souhaitée.
5- si c divise a ou b, solution s = (x ou y) = (c- [ax, yb]) / [b, a] = C / [b, a] + [ax, yb] / [b , a] = S + [ax, yb] / [b, a] où S est naturel donc ax / b ou by / a aurait désormais des solutions directes non négatives qui sont respectivement x = b ou y = a. (notez que les solutions peuvent être des valeurs nulles au cas où des solutions arbitraires précédentes seraient révélées négatives)
lorsque le programme atteint ce stade, une gamme plus étroite de solutions pour x = (c-yb) / a est balayée à la place, grâce à la congruence, de balayer de plus grandes gammes de nombres, qui se répètent de manière répétitive par des cycles réguliers. le plus grand champ de recherche est [xa, x + a] où a est le diviseur.
ESSAYEZ-LE
la source
Axiome, 460 octets
ungolf et un test
Dans les autres «solutions» possibles, il y avait un bogue car il tentait de sauvegarder les solutions infinies dans une liste; maintenant, il est imposé la limite de 80 solutions max
la source