Algorithme pour déterminer l'existence en solution de valeurs non négatives pour l'équation linéaire diophantienne

je suis à la recherche d'une méthode pour déterminer s'il existe une solution pour les équations telles que: 3n1+4n2+5n3=456 , où n1,n2, n3 sont des nombres entiers positifs.

ou plus général: y a-t-il zéro ou positif entiers n1,n2,n3 ... cela résout l'équation k1n1+k2n2+k3n3...=m k1, k2, k3 ... et m sont connus des entiers positifs.

je n'ai pas besoin de trouver une solution juste à déterminer si une solution existe.

Edit:

Concernant l'utilisation pratique de cet algorithme:

dans une bibliothèque de communication, je veux décider si un message donné est valide selon sa taille, avant de traiter le message. Par exemple: je sais qu'un message contient zéro ou plus de 3 octets éléments, zéro ou plus de 4 octets éléments, et de zéro ou plus de 5 octets éléments. J'ai reçu un message de 456 octets, et je veux déterminer sa validité avant d'examiner plus en détail son contenu. Bien sûr, l'en-tête du message contient le nombre d'éléments de chaque type, mais je veux faire une première inspection au niveau de la communication-bibliothèque en passant quelque chose comme pair<MsgType,vector<3,4,5>> .

4
demandé sur Calyth 2009-09-23 22:46:28

7 réponses

vous demandez si l'expression habituelle

(xxx|xxxx|xxxxx)*

correspond à xx...x, où x se produit 456 fois.

Voici une solution en O (n+A^2), où a est le plus petit des nombres sur le côté gauche (dans ce cas 3).

supposez que vos nombres sont 6,7,15. Je vais appeler un numéro expressible dans la forme 6x+7y+15z "disponible". Vous devez vérifier si un numéro est disponible.

Si vous êtes en mesure d'obtenir un certain nombre n, alors sûrement, vous serez en mesure d'obtenir n+6 n+12 n+18 - en général, n+6 k pour tout k >= 0. De l'autre côté, si vous ne parvenez pas à obtenir un nombre n, alors n-6 est sûrement pas disponible (si vous pourriez obtenir (n-6), alors (n-6)+6=n serait disponible), ce qui signifie n-12 n-18, n-6k ne sont pas disponibles non plus.

supposons que vous ayez déterminé que 15 est disponible mais que 9 ne l'est pas. Dans notre cas, 15=6*0+7*0+15*1 mais ne sera pas en mesure d'obtenir 9 dans de toute façon. Ainsi, par notre raisonnement précédent, 15+6k est disponible pour tous k >= 0 et 9-6k pour tous k >= 0 n'est pas. Si vous avez un nombre qui divisé par 6 donne 3 comme reste (3, 9, 15, 21, ...) vous pouvez répondre rapidement: les nombres <= 9 ne sont pas disponibles, les nombres >= 15 le sont.

Il suffit de déterminer pour tous les restes de la division par 6 (0,1,2,3,4,5) quel est le plus petit nombre qui est disponible. (Je viens de montrer que ce nombre pour le reste 3 est de 15).

comment le faire: créez un graphique avec des sommets 0,1,2,3,4,5. Pour tous les nombres k que vous êtes donné (7,15-nous ignorons 6) Ajouter un bord de x à (x + k) mod 6. Donner du poids (x + k) div 6. Utilisez algorithme de Dijkstra en utilisant 0 comme noeud initial. Les distances trouvées par l'algorithme seront exactement les nombres que nous cherchons.

Dans notre cas (6,7,15) le nombre 7 donne lieu à 0 -> 1 (poids 1), 1 -> 2 (poids 1), 2 -> 3 (Poids 1),..., 5 -> 0 (poids 1) et le nombre de 15 donne 0 -> 3 (poids 2), 1 -> 4 (poids 2), ..., 5 - > 1 (Poids 2). Le chemin le plus court de 0 à 3 a un bord - son poids est de 2. Donc 6*2 + 3 = 15 est le plus petit nombre qui donne 3 comme reste. 6*1 + 3 = 9 n'est pas disponible (bien, nous avons vérifié cela auparavant à la main).

et quel est le lien avec les expressions régulières? Eh bien, chaque expression régulière a un automate fini équivalent, et j'en ai construit un ils.

ce problème, avec plusieurs requêtes autorisées, est apparu sur le Olympiade polonaise et j'ai traduit la solution. Si vous entendez quelqu'un dire que l'informatique n'est pas utile aux vrais programmeurs, frappez-le.

12
répondu sdcvvc 2009-09-24 13:28:33

Selon ce , si le plus grand facteur commun de {n1, n2, n3, ...} n'est pas un diviseur de m, puis vous n'avez pas de solution. Cette page montre un exemple de just {n1, n2} mais il s'étend à de plus grands systèmes. Le nouveau problème est d'écrire un algorithme pour trouver le plus grand facteur commun, mais c'est trivial à la lumière du problème original.

donc une partie de votre algorithme trouve le gcf({n1,n2,...}), puis voir si il est un facteur de m. Si c' n'est-ce pas, alors aucune solution n'existe. Cela ne montre pas pleinement qu'une solution existe, mais cela peut rapidement vous montrer qu'il n'y en a pas, ce qui est encore utile.

3
répondu dharga 2009-09-23 19:06:03

on dirait que vous parlez d'un système d'inégalités entier contraintes. La réalité est que vous résolvez pour ce système:

k1n1+k2n2+k3n3...=m
n1 >= 0
n2 >= 0
n3 >= 0

et la contrainte supplémentaire que n1, n2, n3 sont des entiers. C'est un programmation linéaire problème. Malheureusement pour vous, le cas général de résoudre un tel système avec des contraintes entières est NP-complète . Cependant, il existe de nombreux algorithmes qui le résoudront pour vous.

2
répondu Welbog 2009-09-23 18:58:35

ceci est lié au problème de pièce de Frobenius , qui n'a pas été résolu pour n>3.

2
répondu lhf 2009-09-24 11:48:58

Une force brute approche (pseudo-code):

def a = 3
def b = 4
def c = 5
def x = 456

for n1 = a to int(x / a) + 1 step a
  for n2 =b to int(x / b) + 1 step b
    for n3 = c to int(x / c) + 1 step c
      if a * n1 + b * n2 + c * n3 = x then
        print n1, n2, n3

Voir aussi http://mail.python.org/pipermail/python-list/2000-April/031714.html

EDIT: dans une bibliothèque de communication, cela n'aurait aucun sens, car cela doit fonctionner immédiatement. Dans L'application de L'OP j'utiliserais probablement une sorte de hachage, mais son approche semble intéressante.

1
répondu Robert Harvey 2009-09-23 21:11:13

voici quelque chose sur l'affaire des 2 nombres. Je n'ai pas encore trouvé comment le dimensionner:

étant donné 2 entiers relativement premiers x et y, il existe des entiers positifs a et b tels que ax+by=c pour tous c>=(x-1)(y-1)

fondamentalement, cela fonctionne parce que , si vous assumez x<y , vous pouvez exprimer tous les entiers mod x avec (0, y, 2y, 3Y,..., (x-1) y). Maintenant, en ajoutant un certain multiple positif de x, vous pouvez atteindre tous les entiers entre [(x-1)(y-1) (x-1)y], comme tous les nombres entiers compris entre (x-1)(y-1) et (x-1)y-1 a été exprimé précédemment.

  1. PGCD(x,y). Si c n'est pas un multiple, retournez false.
  2. si GCD(x,y) > 1, diviser x, y, c par GCD
  3. If c > (x-1) (y-1), return true
  4. d'Autre force brute

et pour la force brute:

if int(c/y) >= c*y^(-1) mod x, return true, 
else return false
1
répondu Joe Arasin 2009-09-24 00:51:38

peut-être que l'information suivante n'est pas pertinente, parce qu'elle ne gère pas la situation générale, mais...

si le problème est de déterminer si un entier positif K peut être formé comme une somme 3*n1 + 4*n2 + 5*n3 , pour des entiers nonnégatifs n1, n2, n3, alors la réponse est" oui", pour K >= 3.

Rosen bien connu des manuels scolaires Mathématiques Discrètes et de ses Applications , p. 287 de la sixième édition, prouve que "chaque montant d'affranchissement de 12 cents ou plus peut être formé en utilisant seulement des timbres de 4 cents et 5 cents, " en utilisant l'induction.

l'étape de base est que l'affranchissement de 12 cents peut être formé avec 3 timbres de quatre cents.

l'étape d'induction considère que si P(k) est vrai en utilisant des timbres à quatre cents, il suffit de remplacer un timbre à quatre cents par un timbre à cinq cents pour montrer que P(k+1) est vrai. SI P (k) est vrai en n'utilisant pas de timbres de quatre cents, alors, parce que k>=12, nous avons besoin d'au moins 3,5 cents les timbres pour former notre Somme, et 3 timbres de cinq cents peuvent être remplacés par 4 timbres de quatre cents pour atteindre k+1.

pour étendre la solution ci-dessus pour ce problème nécessite juste de considérer quelques cas supplémentaires.

1
répondu bbg 2009-09-25 19:30:25