le théorème des restes chinois nous dit que nous pouvons toujours trouver un nombre qui produit tous les restes requis sous différents modules premiers. Votre objectif est d'écrire du code pour sortir un tel nombre en temps polynomial. Le code le plus court gagne.
Par exemple, supposons qu'on nous donne ces contraintes ( %
représente le mod):
n % 7 == 2
n % 5 == 4
n % 11 == 0
Une solution est n=44
. La première contrainte est satisfaite parce que 44 = 6*7 + 2
, et il en 44
est de même pour le reste 2
divisé par 7
, et donc 44 % 7 == 2
. Les deux autres contraintes sont également respectées. Il existe d'autres solutions, telles que n=814
et n=-341
.
Contribution
Une liste de paires non vide (p_i,a_i)
, où chaque module p_i
est un nombre premier distinct et chaque cible a_i
est un nombre naturel dans la plage 0 <= a_i < p_i
. Vous pouvez prendre des informations sous la forme qui vous convient; il n'est pas nécessaire que ce soit une liste de paires. Vous ne pouvez pas supposer que l'entrée est triée.
Production
Un entier n
tel que n % p_i == a_i
pour chaque index i
. Il n'est pas nécessaire que cette valeur soit la plus petite et peut être négative.
Restriction temporelle polynomiale
Pour éviter des solutions bon marché qui tentent simplement n=0
, n=1
, n=2
et ainsi de suite, votre code doit être exécuté en temps polynomial dans la longueur de l'entrée . Notez qu'un nombre m
dans l'entrée a une longueur Θ(log m)
, donc m
lui-même n'est pas polynomial dans sa longueur. Cela signifie que vous ne pouvez pas compter m
ou effectuer une opération m
, mais vous pouvez calculer des opérations arithmétiques sur les valeurs.
Vous ne pouvez pas utiliser un format d'entrée inefficace comme unaire pour contourner ce problème.
Autres interdictions
Les fonctions intégrées permettant d'effectuer les opérations suivantes ne sont pas autorisées: implémenter le théorème du reste chinois, résoudre des équations ou des nombres de facteurs.
Vous pouvez utiliser des fonctions intégrées pour trouver des mods et effectuer des additions, des soustractions, des multiplications et des exponentiations modulaires (avec un exposant de nombres naturels). Vous ne pouvez pas utiliser d'autres opérations modulaires intégrées, notamment l'inverse modulaire, la division et la recherche d'ordres.
Cas de test
Ceux-ci donnent la plus petite solution non négative. Votre réponse peut être différente. Il est probablement préférable de vérifier directement que votre sortie satisfait à chaque contrainte.
[(5, 3)]
3
[(7, 2), (5, 4), (11, 0)]
44
[(5, 1), (73, 4), (59, 30), (701, 53), (139, 112)]
1770977011
[(982451653, 778102454), (452930477, 133039003)]
68121500720666070
Réponses:
Mathematica,
555145L'inverse modulaire est interdit, mais l'exponentiation modulaire est autorisée. Par le petit théorème de Fermat,
n^(-1) % p == n^(p-2) % p
.Exemple:
Juste pour le fun:
la source
PowerMod[#2,#-2,#]
et je ne pense pas non plus qu'il soit nécessaire de nommer la fonction, la ramenant à 48.Python 2,
165101999885 octetsUtiliser le petit théorème de Fermat comme les autres réponses. Ne prend pas la peine de garder la somme finale dans la plage modulaire, car nous ne sommes pas intéressés par la plus petite solution. Merci Volatility pour avoir économisé 13 octets.
la source
for
.x/a*b*pow(x/a,a-2,a)for a,b in l
devrait marcher.Pyth,
40373629Utilise le petit théorème de Fermat, grâce à l'alephalphe. Calcule à l'aide de cette formule .
la source
Rubis, 129
Eh bien, camarades, il semble que les solutions Ruby doivent être plus longues car l'exponentiation modulaire n'est pas disponible sans charger la bibliothèque openssl et effectuer des conversions vers OpenSSL :: BN. Je me suis quand même amusé à l'écrire:
la source
require
,eval
ouputs
.Python 2, 61
Cela utilise une variation de la construction du produit que d'autres réponses utilisent.
L'idée est de boucler sur les contraintes et de mettre à jour la solution
n
pour respecter la contrainte actuelle sans gâcher les précédentes. Pour ce faire, nous suivons le produitP
des nombres premiers vus jusqu'à présent, et observons que l'ajout d'un multiple deP
n'a aucun effet modulo aucun nombre premier déjà vu.Donc, nous devons juste changer
n
pour satisfairen%p == a
en ajoutant le bon multiple deP
. Nous résolvons pour le coefficientc
:(n + P*c) % p == a
Cela nécessite que
c = (a-n) * P^(-1)
, où l'inverse est pris modulop
. Comme d'autres le notent, l'inverse peut être calculé par le petit théorème de Fermat commeP^(-1) = pow(P,p-2,p)
. Donc,c = (a-n) * pow(P,p-2,p)
et nous mettons à journ
parn+= P * (a-n) * pow(P,p-2,p)
.la source
Haskell,
68octetsUsage:
f [(5,1), (73,4), (59,30), (701,53), (139,112)]
->142360350966
.Edit: maintenant avec une fonction "power / mod" rapide. Ancienne version (68 octets) avec fonction d'alimentation intégrée:
la source