Einführung
In dieser Herausforderung werden wir uns mit einem bestimmten unendlichen ungerichteten Graphen befassen, den ich den Hochteiler-Graphen nenne . Seine Knoten sind die ganzen Zahlen ab 2. Es gibt eine Kante zwischen zwei Knoten a <b, wenn a b und a 2 ≥ b teilt . Der durch den Bereich von 2 bis 18 gebildete Teilgraph sieht folgendermaßen aus:
16-8 12 18
\|/ |/|
4 6 9 10 15 14
| |/ |/ |
2 3 5 7 11 13 17
Es kann gezeigt werden, dass der unendliche Hochteilergraph verbunden ist, sodass wir nach dem kürzesten Weg zwischen zwei Knoten fragen können.
Ein- und Ausgabe
Ihre Eingaben sind zwei ganze Zahlen a und b . Sie können annehmen, dass 2 ≤ a ≤ b <1000 ist . Ihre Ausgabe ist die Länge des kürzesten Pfades zwischen a und b im unendlichen Hochdivisor-Diagramm. Dies bedeutet die Anzahl der Kanten im Pfad.
Möglicherweise ist die folgende Tatsache hilfreich: Es gibt immer einen optimalen Pfad von a nach b , der zuerst zunimmt und dann abnimmt, und es werden nur Knoten besucht, die strikt kleiner als 2b 2 sind . Da b <1000 ist, müssen Sie insbesondere nur Knoten mit weniger als 2 000 000 berücksichtigen.
Beispiele
Betrachten Sie die Eingänge 3
und 32
. Ein möglicher Weg zwischen den Knoten 3 und 32 ist
3 -- 6 -- 12 -- 96 -- 32
Dieser Pfad hat vier Kanten und es stellt sich heraus, dass es keine kürzeren Pfade gibt. Daher ist die Ausgabe korrekt 4
.
Als weiteres Beispiel wird ein optimaler Weg für 2
und 25
ist
2 -- 4 -- 8 -- 40 -- 200 -- 25
also die richtige ausgabe ist 5
. In diesem Fall enthält kein optimaler Pfad den Knoten 50 = lcm(2, 25)
.
Regeln und Wertung
Sie können ein vollständiges Programm oder eine Funktion schreiben. Die niedrigste Byteanzahl gewinnt, und Standardlücken sind nicht zulässig. Es gibt keine Zeit- oder Speicherbeschränkungen, daher ist Brute Forcing zulässig.
Testfälle
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
verstößt Mathematica gegen die Vorgabe von Standardlücken? Wenn ja, lass es mich einfach wissen und ich werde meinen Beitrag löschen.Antworten:
Matlab,
218190175 BytesVielen Dank an @beaker für die Verknüpfung im Schritt zur Listenverlängerung!
Dies ist eine relativ einfache dijkstra-Implementierung:
Keine Faltung heute
quelle
l=zeros(1,a*b);
kannst du verwendenl(a*b)=0;
, was das gleiche tutJavaScript (ES6), 186 Byte
Verwendet eine Hilfsfunktion
g
, um alle aufsteigenden Pfade vonm
undn
bis zum angegebenen Grenzwert zu berechnen , summiert dann die Pfade und gibt den niedrigsten Wert zurück.quelle
Mathematica 98 Bytes
Ich gehe davon aus, dass die eingebaute Funktion
FindShortestPath
nicht gegen die Einschränkung über Standard-Regelungslücken verstößt. Wenn ja, lass es mich einfach wissen und ich werde diese Einsendung löschen.Brute Force, daher langsam mit großen Werten von
b
. Ich denke immer noch über Möglichkeiten nach, es zu beschleunigen.Dadurch wird ein Diagramm mit den entsprechenden Kanten zwischen den Knoten von
a
bis erstelltb^2
.FindShortestPath
findet den kürzesten Weg in der Grafik.Length
zählt die Knoten;Length -1
ist die Anzahl der Kanten.Thread[# <-> Range[2, #] #] &
Erzeugt die Kanten des vollständigen Graphen. Zum BeispielThread[# <-> Range[2, #] #]&[5]
würde die Kanten erzeugen{5 <-> 2*5, 5 <-> 3*5, 5 <-> 4*5, 5 <-> 5*5}
, das heißt{5 <-> 10, 5 <-> 15, 5 <-> 20, 5 <-> 25}
.quelle
Matlab
(195) (185) (181) (179)(173)Beispiel eines Funktionsaufrufs:
Alle Testfälle sind erfüllt
Erläuterung:
Bevor wir mit Erklärungen beginnen, wollen wir einige Lemmas "nicht grüne" beweisen:
Lemma (1): Ein optimaler Weg zwischen zwei beliebigen Zahlen
(a,b)
besteht darin, dass die Knoten zuerst zunehmen und dann abnehmen.Warum ? Dies ist einfach bewiesen, weil der maximale ganzzahlige Betrag, der eine Zahl dividiert,
a
jeweils so groß ist wie die Zahla
selbst. Als kluger Ansatz müssen wira
so viel wie möglich multiplizieren , um sie ausreichend zu vergrößern, und dann durch größere Werte dividieren. Wenn wir jemals den umgekehrten Weg gehen, wird die Zahla
kleiner, sodass wir unnötig mehr Iterationen benötigen, um sie allmählich zu multiplizieren, ohne dass wir darauf verzichten müssen.Lemma (2): Von einer Zahl
a
zub
, wenngcd(a,b)=1
a
multipliziert mitb
, wennb
größer alsa
es ist, wird multipliziert mit einer bekannten Zahlc
, wenn nachgcd>1
a
und nach multipliziert werden muss mit dem größten Divisor vonb/gcd
namedd
, der die Bedingunga >= d
auch dann überprüft, wenn allesd
das ist Minimum sind größer alsa
,a
erhälta*c
wieder.Diese Annahme ist einfach zu beweisen, dass jeder Startknoten
a
multipliziert werden muss, bis er das kleinste Vielfache von erreicht,a
undb
daher multiplizieren wir entweder mit den Anteilen desb*gcd
Anfangs mit dem Maximum, was die Hauptbedingung verifiziert, die immer den kürzesten Weg zu smp garantiert, bevor der Divisionsprozess beginnt. oder wennd
nicht verfügbar, wird eine Zahlc
mit multiplizierta
, um eine gültige Bedingunga>=d
für diese erste Stufe zu erstellen .Lemma (3): Aus einem graphen ultimum mehr von
a
zub
, den GCD dieser Zahl undb
istb
selbstNun, dies ist nur eine Folge der vorherigen Manipulationen, und die letzten verbleibenden Schritte werden auch schrittweise durch den größten Teiler geteilt, der seine Quadratwurzel nicht überschreitet.
Dilemma: Was ist die optimale Zahl
c
, die iterativ multipliziert werden mussa
, um direkt zur Eröffnungsbedingung für Stufe 1 und dann zum Ultimum zu gelangen?Gute Frage, für jede einfache Situation gibt es eine einfache Parade. Nehmen wir also ein Beispiel von zwei Enden an, die
(a,b)=(4,26)
wie folgt faktorisiert sind:Neben der
gcd=2
kleinsten ganzen Zahl Weicht durch multiplizieren müssen ,2
um zu erreichen13
ist7
, aber es ist offensichtlich ausgeschlossen, Cuz es größer als 2 ist, so dass ein Quadrat ist.Das Aussehen im
(a,b)=(10,26)
obigen zweiten Beispielc
wird als die niedrigste ganze Zahl gemessen1
,5
die übersteigt,13/5
und erfüllt daher die Bedingung der Graphskalierung, dh3
, der nächste Schritt ist hier das Multiplizieren mit3
Warum ? Dies liegt daran, dass, sobald wir mit multiplizieren müssen
2*13/gcd=13
, um der zweiten Seite der Tabelle zu entsprechen, der zuvor hinzugefügte Junk-Betrag optimal klein ist und die Bewegung entlang des Diagramms minimiert wird, wenn wir jemals mit einem höheren Wert multipliziert werden, beispielsweise10
der Chance, durch zu dividieren Die kürzeste Zeit verkürzt sich, und sie wäre um einen weiteren Teilungsschritt erhöht worden, um unser Ziel zu erreichen2*13
. welche sind aufgezählt:13*2*5*10/2*5
dann13*2*5/5
. Dabei ist hier offensichtlich die zu teilende Zahl5*3<13*2
und noch eins ........ HAIL MATHS ...
Dies sind meine Vergleichsergebnisse mit denen von @flawr. Achten Sie nur darauf, dass ich eine Obergrenze für die Zeitausführung festgelegt habe, wobei der Algorithmus von flawr berücksichtigt wird. Es dauert zu lange!
Sie können den Start- und End-Scanbereich als Variablen a und b in die Kopfzeile des online kompilierbaren Codes einfügen.
quelle