Вступление
В этой задаче мы будем иметь дело с неким бесконечным неориентированным графом, который я называю графом с высокими делителями . Его узлами являются целые числа, начиная с 2. Между двумя узлами a <b есть ребро, если a делит b и a 2 ≥ b . Подграф, образованный диапазоном от 2 до 18, выглядит так:
16-8 12 18
\|/ |/|
4 6 9 10 15 14
| |/ |/ |
2 3 5 7 11 13 17
Можно показать, что бесконечный граф с высокими делителями связан, поэтому мы можем спросить о кратчайшем пути между двумя узлами.
Вход и выход
Ваши входные данные - два целых числа a и b . Можно предположить, что 2 ≤ a ≤ b <1000 . Ваш вывод - длина кратчайшего пути между a и b в бесконечном графе высокого делителя. Это означает количество ребер в пути.
Может оказаться полезным следующий факт: всегда существует оптимальный путь от а до б который сначала увеличивается, а затем уменьшается, и посещает только те узлы, которые строго меньше 2b 2 . В частности, поскольку b <1000, вам нужно учитывать только узлы менее 2 000 000.
Примеры
Рассмотрим входы 3
и 32
. Одним из возможных путей между узлами 3 и 32 является
3 -- 6 -- 12 -- 96 -- 32
Этот путь имеет четыре ребра, и оказывается, что нет более коротких путей, поэтому правильный вывод 4
.
В качестве другого примера, оптимальный путь 2
и25
является
2 -- 4 -- 8 -- 40 -- 200 -- 25
поэтому правильный вывод 5
. В этом случае ни один оптимальный путь не содержит узел 50 = lcm(2, 25)
.
Правила и оценки
Вы можете написать полную программу или функцию. Побеждает меньшее количество байтов, и стандартные лазейки запрещены. Нет ограничений по времени или памяти, поэтому грубое принуждение разрешено.
Контрольные примеры
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
нарушает ограничение на стандартные лазейки? Если это так, просто дайте мне знать, и я удалю свою заявку.Ответы:
Matlab,
218190175 байтовСпасибо @beaker за ярлык в шаге удлинения списка!
Это относительно простая реализация dijkstra:
сегодня нет свертки
источник
l=zeros(1,a*b);
тебя можно использоватьl(a*b)=0;
, что делает то же самоеJavaScript (ES6), 186 байт
Использует вспомогательную функцию
g
для вычисления всех восходящих путей отm
иn
в свою очередь до заданного предела, затем суммирует пути вместе и возвращает самое низкое значение.источник
Mathematica 98 байт
Я предполагаю, что встроенная функция
FindShortestPath
не нарушает ограничение на стандартные лазейки. Если это произойдет, просто дайте мне знать, и я удалю это представление.Грубая сила, следовательно, медленная с большими значениями
b
. Я все еще думаю о способах ускорить это.Это устанавливает график с соответствующими ребрами между узлами от
a
доb^2
.FindShortestPath
находит кратчайший путь в графе.Length
считает узлы;Length -1
количество реберThread[# <-> Range[2, #] #] &
производит ребра полного графа. Например,Thread[# <-> Range[2, #] #]&[5]
будет производить края{5 <-> 2*5, 5 <-> 3*5, 5 <-> 4*5, 5 <-> 5*5}
, то есть{5 <-> 10, 5 <-> 15, 5 <-> 20, 5 <-> 25}
.источник
Matlab
(195) (185) (181) (179)(173)Пример вызова функции:
Все тесты выполнены
Объяснение:
Прежде чем начать с объяснений, давайте докажем некоторые леммы "не зеленые":
Лемма (1). Оптимальный путь между любыми двумя числами
(a,b)
существует таким образом, что узлы сначала увеличиваются, а затем уменьшаются.Почему ? Это просто доказано, потому что максимальное целое число, которое делит любое число
a
, соответственно больше, чем само числоa
, поэтому в качестве разумного подхода мы должны выбрать умножениеa
настолько, насколько это возможно, чтобы сделать его достаточно большим, а затем делить на большие значения. Если когда-нибудь мы сделаемa
обратное, число сжимается, поэтому нам нужно излишне больше итераций, чтобы постепенно умножать его, что мы обойдемся.Лемма (2): от числа
a
доb
, еслиgcd(a,b)=1
a
умножаетсяb
, еслиb
больше , чемa
она будет умножаться на известное числоc
, еслиgcd>1
a
необходимо умножить постепенно самым большим делителемb/gcd
имени ,d
что проверяет условиеa >= d
также , когда всеd
«S , а именно минимум больше чемa
,a
получаетa*c
снова.Это предположение просто, чтобы доказать, что любой начальный узел
a
должен быть умножен до тех пор, пока он не достигнет наименьшего кратного,a
иb
поэтому мы либо умножаем на пропорцииb*gcd
начала до максимума, который проверяет основное условие, которое гарантирует всегда кратчайший путь к smp до начала процесса деления или когда номерd
недоступен, числоc
умножается на,a
чтобы создать действительное условиеa>=d
для этой первой стадии.Лемма (3): Из граф-ultimum кратно
a
кb
, НОД этого числа , иb
этоb
само по себеНу, это всего лишь следствие предыдущих манипуляций, и последние оставшиеся шаги также делаются постепенно делением на самый большой делитель, который не превышает его квадратный корень.
Дилемма: Какое оптимальное число
c
будет умножено на итеративное умножение,a
которое привело бы прямо к условию открытия для стадии 1, а затем к ультимуму?Хороший вопрос, для любой простой ситуации существует простое парирование, поэтому предположим пример с двумя концами,
(a,b)=(4,26)
разложенными так:Отдельно от
gcd=2
наименьшего целого числа, которое должно быть умножено на,2
чтобы достичь13
is7
, но это, очевидно, исключено, потому что это больше, чем 2, поэтому квадрат возводится в квадрат.Внешний вид во втором приведенном
(a,b)=(10,26)
выше примереc
измеряется как наименьшее целое число из1
до5
которого превышает13/5
следовательно , он удовлетворяет условию граф-масштабирования, который является3
, поэтому следующий шаг здесь умножая на3
Почему ? это потому, что, как только мы должны умножить на
2*13/gcd=13
чтобы соответствовать второй стороне таблицы, количество мусора, которое мы добавили ранее, является оптимально наименьшим, и перемещение по графику минимизируется, если мы когда-либо умножаем на большее значение, как10
вероятность деления на Наименьшее количество раз уменьшается, и это было бы увеличено еще на 1 делительный шаг для достижения нашей цели2*13
. которые перечисляются:13*2*5*10/2*5
тогда13*2*5/5
. Хотя, очевидно, здесь число, которое будет разделено на5*3<13*2
и еще одна вещь ........ ГРАДНЫЕ МАТЫ ...
Это мои сравнительные результаты с @flawr, просто обратите внимание на то, что я сделал верхнюю границу для времени выполнения, сохраняющего алгоритм flawr, это занимает слишком много времени!
Вы можете вставить начальный и конечный диапазоны сканирования в качестве переменных a и b в заголовок компилируемого кода.
источник