Кратчайшие пути в графе делителей


15

Вступление

В этой задаче мы будем иметь дело с неким бесконечным неориентированным графом, который я называю графом с высокими делителями . Его узлами являются целые числа, начиная с 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

У меня есть идея, которая не является грубой силой, как я предполагал, она считает наименьшее кратное из двух чисел, постепенно умножается на степень два, пока она не появится, а затем постепенно делится на квадрат, пока не появится второе число, у меня нет времени реализовать сейчас, хотя: /
Abr001am

Zgarb, Mathematica FindShortestPath нарушает ограничение на стандартные лазейки? Если это так, просто дайте мне знать, и я удалю свою заявку.
DavidC

@ ДэвидC Я не считаю это лазейкой. Соответствующий ответ на самом деле имеет оценку 0.
Zgarb

Ответы:


4

Matlab, 218 190 175 байтов

function f(a,b);q=a;l(b)=0;l(a)=1;while~l(b);x=q(1);q=q(2:end);l(end+1:x^2)=0;g=x+1:x^2;s=2:x-1;u=[g(~mod(g,x)),s(~mod(x,s)&s.^2>=x)];u=u(~l(u));q=[q,u];l(u)=l(x)+1;end;l(b)-1

Спасибо @beaker за ярлык в шаге удлинения списка!

Это относительно простая реализация dijkstra:

q=a;                  %queue
l(b)=0;       %list of path lengths
l(a)=1;
while~l(b);         %if there is no predecessor to b
    x=q(1);         %get first queue element
    q=q(2:end);
    %add edges 
    l(end+1:x^2)=0;% lengthen predecessor list if too short
    g=x+1:x^2;      % g=greater neighbours
    s=2:x-1;        % s=smaller neighbours %keep only valid/unvisited neighbours 
    u=[g(~mod(g,x)),s(~mod(x,s)&s.^2>=x)]; %-1byte
    u=u(~l(u));
    q=[q,u];      %add only hte valid nodes edges to queue
    l(u)=l(x)+1;       %mark x as predecessor  
end;
l(b)-1 %output length to the end of the path

сегодня нет свертки


2
Вместо l=zeros(1,a*b);тебя можно использовать l(a*b)=0;, что делает то же самое
Луис Мендо

увы .... еще 10 байт позади тебя.
Abr001am

1

JavaScript (ES6), 186 байт

(m,n)=>(g=i=>{for(q=[i],r=[],r[i]=j=0;i=q[j++];)for(k=i+i;k<=i*i&(k<m*m*2|k<n*n*2);k+=i)r[k]-r[i]<2?0:r[q.push(k),k]=r[i]+1},g(m),s=r,g(n),Math.min(...r.map((i,j)=>i+s[j]).filter(i=>i)))

Использует вспомогательную функцию gдля вычисления всех восходящих путей от mи nв свою очередь до заданного предела, затем суммирует пути вместе и возвращает самое низкое значение.


1

Mathematica 98 байт

Я предполагаю, что встроенная функция FindShortestPathне нарушает ограничение на стандартные лазейки. Если это произойдет, просто дайте мне знать, и я удалю это представление.

Грубая сила, следовательно, медленная с большими значениями b . Я все еще думаю о способах ускорить это.

h@{a_,b_}:=Length@FindShortestPath[Graph[Apply[Join,Thread[#<->Range[2,#] #]&/@Range[b^2]]],a,b]-1

Это устанавливает график с соответствующими ребрами между узлами от 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}.


1

Matlab (195) (185) (181) (179)(173)

Примечание: я, пользователь Agawa001, лично подтверждаю, что победил пользователя @flawr, воспользовавшись его помощью.

 function t(a,b,p),for r=0:1,d=(b*~r+r*a)/gcd(a,b);while(d>1)p=p+1;e=find(~rem(d,1:d));f=max(e(a^(1-r/2)>=e));a=a*min([find(1:a*a>=b) a])^~(f-1);d=d/f;a=a*f^(1-2*r);end,end,p
  • Эта функция отличается от других, она следует за кучей чисто математических вычислений и факторизаций, но не имеет ничего общего с путями или графиками.
  • Пример вызова функции:

     t(2,3,0)
    
     p =
    
     4
    

    Все тесты выполнены

  • Объяснение:

Прежде чем начать с объяснений, давайте докажем некоторые леммы "не зеленые":

Лемма (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)разложенными так:

  2 | 2
  2 | 13

Отдельно от gcd=2 наименьшего целого числа, которое должно быть умножено на, 2чтобы достичь 13is 7, но это, очевидно, исключено, потому что это больше, чем 2, поэтому квадрат возводится в квадрат.

  2 | 2 
  5 | 13

Внешний вид во втором приведенном (a,b)=(10,26)выше примере cизмеряется как наименьшее целое число из1 до 5которого превышает 13/5следовательно , он удовлетворяет условию граф-масштабирования, который является 3, поэтому следующий шаг здесь умножая на3

  2 | 2 
  5 | 13
  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 в заголовок компилируемого кода.


Вау, это удивительно. Я не ожидал, что оптимальные пути могут быть построены простым способом. Ждем объяснений ...
Згарб

@Zgarb Я сделал тривиальное объяснение в комментариях к главному посту, я уточню, когда закончу играть в гольф, кстати, что за уникальная приятная задача!
Abr001am

@ Zgarb доказательство свежее из духовки !!!!
Abr001am
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.