introduction
Dans ce défi, nous aurons affaire à un certain graphe infini non orienté, que j'appelle le graphe à diviseur élevé . Ses nœuds sont les entiers à partir de 2. Il y a un bord entre deux nœuds a <b si a divise b et a 2 ≥ b . Le sous-graphique formé par la plage de 2 à 18 ressemble à ceci:
16-8 12 18
\|/ |/|
4 6 9 10 15 14
| |/ |/ |
2 3 5 7 11 13 17
Il peut être démontré que le graphe diviseur infini est connecté, nous pouvons donc nous interroger sur le chemin le plus court entre deux nœuds.
Entrée et sortie
Vos entrées sont deux entiers a et b . Vous pouvez supposer que 2 ≤ a ≤ b <1000 . Votre sortie est la longueur du chemin le plus court entre a et b dans le graphique de diviseur élevé infini. Cela signifie le nombre d'arêtes dans le chemin.
Vous pouvez trouver le fait suivant utile: il existe toujours un chemin optimal de a vers b qui augmente d'abord puis diminue, et ne visite que les nœuds strictement inférieurs à 2b 2 . En particulier, puisque b <1000, il suffit de considérer les nœuds inférieurs à 2 000 000.
Exemples
Considérez les entrées 3
et 32
. Un chemin possible entre les nœuds 3 et 32 est
3 -- 6 -- 12 -- 96 -- 32
Ce chemin a quatre bords, et il s'avère qu'il n'y a pas de chemins plus courts, donc la sortie correcte est 4
.
Comme autre exemple, un chemin optimal pour 2
et 25
est
2 -- 4 -- 8 -- 40 -- 200 -- 25
donc la sortie correcte est 5
. Dans ce cas, aucun chemin optimal ne contient le nœud 50 = lcm(2, 25)
.
Règles et notation
Vous pouvez écrire un programme complet ou une fonction. Le nombre d'octets le plus bas gagne et les failles standard sont interdites. Il n'y a pas de limite de temps ou de mémoire, le forçage brutal est donc autorisé.
Cas de test
2 2 -> 0
2 3 -> 4
2 4 -> 1
2 5 -> 5
3 5 -> 4
6 8 -> 2
8 16 -> 1
12 16 -> 2
16 16 -> 0
2 25 -> 5
3 32 -> 4
2 256 -> 3
60 77 -> 3
56 155 -> 3
339 540 -> 2
6 966 -> 4
7 966 -> 2
11 966 -> 4
2 997 -> 7
991 997 -> 4
FindShortestPath
viole-t-il la contrainte sur les failles standard? Si c'est le cas, faites-le moi savoir et je supprimerai ma soumission.Réponses:
Matlab,
218190175 octetsMerci @beaker pour le raccourci dans l'étape d'allongement de la liste!
Il s'agit d'une implémentation dijkstra relativement simple:
pas de convolution aujourd'hui
la source
l=zeros(1,a*b);
vous pouvez utiliserl(a*b)=0;
, ce qui fait la même choseJavaScript (ES6), 186 octets
Utilise une fonction d'aide
g
pour calculer tous les chemins ascendants à partir dem
etn
à son tour jusqu'à la limite fournie, puis additionne les chemins ensemble et renvoie la valeur la plus basse.la source
Mathematica 98 octets
Je suppose que la fonction intégrée
FindShortestPath
ne viole pas la contrainte sur les failles standard. Si c'est le cas, faites le moi savoir et je supprimerai cette soumission.Force brute, donc lente avec de grandes valeurs de
b
. Je pense toujours à des moyens d'accélérer.Cela crée un graphique avec des arêtes appropriées entre les nœuds de
a
àb^2
.FindShortestPath
trouve le chemin le plus court dans le graphique.Length
compte les nœuds;Length -1
est le nombre d'arêtes.Thread[# <-> Range[2, #] #] &
produit les bords du graphique complet. Par exemple,Thread[# <-> Range[2, #] #]&[5]
produirait les bords{5 <-> 2*5, 5 <-> 3*5, 5 <-> 4*5, 5 <-> 5*5}
, c'est-à-dire{5 <-> 10, 5 <-> 15, 5 <-> 20, 5 <-> 25}
.la source
Matlab
(195) (185) (181) (179)(173)Exemple d'appel de fonction:
Tous les cas de test sont satisfaits
Explication:
Avant de commencer par des explications, prouvons quelques lemmes "non verts":
Lemme (1): Un chemin optimal entre deux nombres
(a,b)
existe d'une manière que les nœuds augmentent d'abord puis diminuent.Pourquoi ? Cela est simplement prouvé parce que le nombre entier maximal qui divise n'importe quel nombre
a
est respectivement grand comme le nombrea
lui-même, donc comme une approche intelligente, nous devons choisir de multipliera
autant que possible pour le rendre suffisamment plus grand, puis en le divisant par des valeurs plus grandes. Si jamais nous faisons le chemin, le nombrea
diminue, nous avons donc besoin inutilement de plus d'itérations pour le multiplier progressivement dont nous sommes dispensés.Lemme (2): D'un nombre
a
àb
, sigcd(a,b)=1
a
est multiplié parb
, sib
est plus granda
qu'il sera multiplié par un nombre connuc
, s'ilgcd>1
a
doit être multiplié progressivement par le plus grand diviseur deb/gcd
nomméd
qui vérifie la conditiona >= d
également lorsque toutd
est à savoir le minimum sont plus grands quea
,a
reçoit àa*c
nouveau.Cette hypothèse est simple pour prouver que tout nœud de départ
a
doit être multiplié jusqu'à ce qu'il atteigne le plus petit multiple dea
etb
donc soit nous multiplions par des proportions deb*gcd
début par le maximum qui vérifie la condition principale, ce qui garantit toujours le chemin le plus court vers smp avant le début du processus de division, ou lorsqu'ild
n'est pas disponible, un nombrec
est multiplié para
pour créer une condition validea>=d
pour cette première étape.Lemme (3): D'un multiple du graphique ultime de
a
àb
, le pgcd de ce nombreb
estb
lui - mêmeEh bien, ce n'est qu'une conséquence des manipulations précédentes, et les dernières étapes restantes sont également effectuées progressivement en divisant par le plus grand diviseur qui ne dépasse pas sa racine carrée.
Dilemme: Quel est le nombre optimal
c
à multiplier de manière itérativea
qui mènerait directement à la condition d'ouverture pour l'étape 1 puis à l'ultimum?Bonne question, pour toute situation simple, il y a une parade simple, donc en supposant un exemple de deux extrémités
(a,b)=(4,26)
factorisées comme ceci:Mis à part le
gcd=2
plus petit entier qui doit être multiplié par2
pour atteindre13
is7
, mais il est évidemment exclu, car il est supérieur à 2, donc a est carré.Appearenlty dans le deuxième exemple
(a,b)=(10,26)
ci - dessusc
est mesuré comme le nombre entier le plus bas1
de5
laquelle dépasse d'13/5
où il satisfait à la condition de mise à l' échelle graphe, qui est3
, de sorte que la prochaine étape est ici en multipliant par3
Pourquoi ? c'est parce que, une fois que nous devons multiplier par
2*13/gcd=13
pour correspondre au deuxième côté du tableau, la quantité d'ordure que nous avons ajoutée avant est de façon optimale la plus petite, et le déplacement le long du graphique est minimisé, si jamais nous multiplions par une valeur plus grande comme10
la chance de diviser par le moins de temps se réduit, et il aurait été augmenté d'une autre étape de division pour atteindre notre objectif2*13
. qui sont énumérés à:13*2*5*10/2*5
alors13*2*5/5
. Alors, évidemment, ici, le nombre à diviser est5*3<13*2
et encore une chose ........ SALUT MATHS ...
Ce sont mes résultats comparatifs avec ceux de @flawr faites juste attention à ce que j'ai fait une limite supérieure pour l'exécution du temps en respectant l'algorithme de flawr, cela prend trop de temps!
Vous pouvez insérer les plages de balayage de début et de fin en tant que variables a et b dans l'en-tête du code compilable en ligne.
la source