Wprowadzenie
W tym wyzwaniu będziemy mieli do czynienia z pewnym nieskończonym niekierowanym wykresem, który nazywam wykresem wysokiego dzielnika . Węzłami są liczbami całkowitymi, począwszy od 2. Nie jest krawędź między dwoma węzłami <b jeśli dzieli b i a 2 ≥ b . Podgraf utworzony przez zakres od 2 do 18 wygląda następująco:
16-8 12 18
\|/ |/|
4 6 9 10 15 14
| |/ |/ |
2 3 5 7 11 13 17
Można pokazać, że wykres nieskończonego wysokiego dzielnika jest połączony, więc możemy zapytać o najkrótszą ścieżkę między dwoma węzłami.
Wejście i wyjście
Twoje dane wejściowe to dwie liczby całkowite a i b . Możesz założyć, że 2 ≤ a ≤ b <1000 . Jego wynik jest długością najkrótszej trasy między i b w nieskończonym wykresie wysokiej dzielnik. Oznacza to liczbę krawędzi na ścieżce.
Przydatny może być następujący fakt: zawsze istnieje optymalna ścieżka od a do b, która najpierw rośnie, a następnie maleje i odwiedza tylko węzły, które są mniejsze niż 2b 2 . W szczególności, ponieważ b <1000 , należy wziąć pod uwagę tylko węzły mniejsze niż 2 000 000.
Przykłady
Rozważ dane wejściowe 3
i 32
. Jedną z możliwych ścieżek między węzłami 3 i 32 jest
3 -- 6 -- 12 -- 96 -- 32
Ta ścieżka ma cztery krawędzie i okazuje się, że nie ma krótszych ścieżek, więc prawidłowy wynik to 4
.
Kolejnym przykładem jest optymalna ścieżka dla 2
i 25
jest
2 -- 4 -- 8 -- 40 -- 200 -- 25
więc poprawne wyjście to 5
. W takim przypadku żadna optymalna ścieżka nie zawiera węzła 50 = lcm(2, 25)
.
Zasady i punktacja
Możesz napisać pełny program lub funkcję. Wygrywa najniższa liczba bajtów, a standardowe luki są niedozwolone. Nie ma ograniczeń czasu ani pamięci, więc dozwolone jest brutalne wymuszanie.
Przypadki testowe
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
narusza ograniczenie dotyczące standardowych luk? Jeśli tak, daj mi znać, a ja usunę swoje zgłoszenie.Odpowiedzi:
Matlab,
218190175 bajtówDzięki @beaker za skrót w kroku wydłużania listy!
Jest to stosunkowo prosta implementacja dijkstra:
dzisiaj nie ma splotu
źródło
l=zeros(1,a*b);
ciebie możesz użyćl(a*b)=0;
, co robi to samoJavaScript (ES6), 186 bajtów
Wykorzystuje funkcję pomocnika
g
obliczyć wszystkie ścieżki rosnacy odm
in
kolejno do podanego limitu, a następnie sumuje ścieżek razem i powroty najniższej wartości.źródło
Mathematica 98 bajtów
Zakładam, że wbudowana funkcja
FindShortestPath
nie narusza ograniczenia dotyczącego standardowych luk. Jeśli tak, daj mi znać, a ja usunę to zgłoszenie.Brutalna siła, a więc powolna z dużymi wartościami
b
. Nadal zastanawiam się, jak to przyspieszyć.Spowoduje to utworzenie wykresu z odpowiednimi krawędziami między węzłami od
a
dob^2
.FindShortestPath
znajduje najkrótszą ścieżkę na wykresie.Length
zlicza węzły;Length -1
to liczba krawędzi.Thread[# <-> Range[2, #] #] &
tworzy krawędzie pełnego wykresu. Na przykładThread[# <-> Range[2, #] #]&[5]
utworzy krawędzie{5 <-> 2*5, 5 <-> 3*5, 5 <-> 4*5, 5 <-> 5*5}
, to znaczy{5 <-> 10, 5 <-> 15, 5 <-> 20, 5 <-> 25}
.źródło
Matlab
(195) (185) (181) (179)(173)Przykład wywołania funkcji:
Wszystkie przypadki testowe są spełnione
Wyjaśnienie:
Zanim zaczniemy od wyjaśnień, dowiedzmy się, że niektóre lematy są „zielone”:
Lemat (1): Optymalna ścieżka między dowolnymi dwoma liczbami
(a,b)
istnieje w taki sposób, że węzły najpierw rosną, a maleją.Dlaczego ? Jest to po prostu udowodnione, ponieważ maksymalna liczba całkowita, która dzieli dowolną liczbę,
a
jest odpowiednio duża jaka
sama liczba , więc jako sprytne podejście musimy wybraća
jak najwięcej pomnożenia, aby było wystarczająco większe, a następnie podzielenie przez większe wartości. Jeśli kiedykolwiek zrobimy to na odwrót, liczba sięa
zmniejszy, więc potrzebujemy niepotrzebnie więcej iteracji, aby pomnożyć ją stopniowo, bez potrzeby.Lemat (2): Od liczby
a
dob
, jeśligcd(a,b)=1
a
jest pomnożony przezb
, jeślib
jest większy niża
będzie pomnożony przez znaną liczbęc
, jeśligcd>1
a
musi być pomnożony przez największy dzielnik ob/gcd
nazwie,d
który sprawdza waruneka >= d
również wtedy, gdy wszystkod
jest mianem minimum jest większe niża
,a
otrzymujea*c
ponownie.To założenie jest proste do udowodnienia każdy węzeł rozpoczęciem
a
należy pomnożyć aż osiągnie najmniejszą wielokrotnośća
ab
więc albo mnożymy przez proporcjachb*gcd
zaczynając od maksimum która weryfikuje główny warunek, który gwarantuje zawsze najkrótsza droga do smp zanim rozpocznie proces podziału, lub gdyd
nie jest dostępny, liczbac
jest mnożona przez,a
aby spełnić waruneka>=d
dla pierwszego etapu.Lemat (3): Od wielokrotności wykresu
a
dob
gcd tej liczby ib
jestb
samCóż, jest to tylko konsekwencja poprzednich manipulacji, a ostatnie pozostałe kroki są również wykonywane stopniowo dzieląc przez największy dzielnik, który nie przekracza pierwiastka kwadratowego.
Dylemat: Jaka jest optymalna liczba, którą
c
należy pomnożyć iteracyjniea
, która prowadziłaby prosto do warunków otwarcia dla etapu 1, a następnie najwyższego?Dobre pytanie, dla każdej prostej sytuacji istnieje prosta parowanie, więc zakładając przykład dwóch zakończeń
(a,b)=(4,26)
tak podzielonych na czynniki:Oprócz
gcd=2
najmniejszej liczby całkowitej, którą należy pomnożyć,2
aby osiągnąć,13
jest7
, ale oczywiście jest wykluczone, ponieważ jest większa niż 2, więc a jest kwadratem.Appearenlty w drugim przykładzie
(a,b)=(10,26)
powyżejc
mierzy się jako najmniejszą liczbę całkowitą od1
do5
przekraczającej13/5
stąd spełnia warunek wykresu zgorzeliny, która jest3
, aby następny krok jest pomnożony przez3
Dlaczego ? Dzieje się tak, ponieważ gdy musimy pomnożyć,
2*13/gcd=13
aby dopasować do drugiej strony tabeli, ilość śmieci dodanych wcześniej jest optymalnie najmniejsza, a poruszanie się po wykresie jest zminimalizowane, jeśli kiedykolwiek pomnożymy przez większą wartość, taką jak10
szansa na podzielenie przez najmniej razy zmniejsza się, a zostałby zwiększony o 1 kolejny krok dzielący, aby osiągnąć nasz cel2*13
. które są wyliczone do:13*2*5*10/2*5
wtedy13*2*5/5
. Chociaż oczywiście tutaj liczba, którą należy podzielić, to5*3<13*2
i jeszcze jedno ... MATY WŁOSÓW ...
To są moje wyniki porównawcze z wynikami @flawr. Zwróć tylko uwagę, że wyznaczyłem górną granicę czasu wykonania zachowując algorytm flawr, to zajmuje zbyt dużo czasu!
Możesz wstawiać początkowe i końcowe zakresy skanowania jako zmienne a i b w nagłówku kompilowanego kodu online.
źródło