возможно ли из a получить b
всем привет, есть два числа, нужно проверить возможно ли получить из числа a другое число b, умножая его на число которое делится на a и посчитать кол-во шагов за которое это можно сделать, например:
a = 2
b = 16
результат такой: 2 --> 4 --> --> 8 -- > 16 ( за 3 шага) в голове нет идей, как это реализовать, пытался через делители числа, но получилось решить только частично. нужна идея для эффективного решения, т.к лимит времени 1.0 сек и ограничение памяти 64мб.
условие задачи тут:
Студенту снится сон. Во сне он ходит по городу, в котором ужасно много трактиров. В каждом трактире выпивает кружку эля. Все трактиры пронумерованы целыми положительными числами, и из трактира с номером n можно пойти только в трактир с номером, который делится на n. Начинается сон в трактире с номером a. Студент знает, что ему надо попасть в трактир с номером b. При этом, понятно, хочет по пути выпить как можно больше эля. Если он не может дойти из трактира a в трактир b, то сразу просыпается в холодном поту.
Ответы (1 шт):
Если b не делится на a, то добраться из a в b студент не может.
Пусть b делится на a.
Разложим на простые a = p1u1 p2u2 ..., b = p1v1 p2v2 ..., где pi - все простые числа.
b делится на a, значит ∀ i, ui ≤ vi.
Если с между a и b, то a < c < b, a делит c, с делит b. Разложим на простые c = p1w1 p2w2 ...
∀ i, ui ≤ wi ≤ vi
Вместо того чтобы рассматривать делители, будет рассматривать вектора (wi). Начинается цепочка векторов в (ui), заканчивается в (vi). Каждый шаг увеличивает один или несколько элементов w на единицу или больше. Минимальный шаг увеличивает один элемент на единицу. Всего можно сделать шагов ∑i(vi - ui).
Утверждение: число шагов из a в b равно числу шагов из 1 в n (= b / a). Доказательство - почти очевидно.
Программа ниже разлагает n на простые множители и конструирует из них маршрут студента. Сложность O(√(b/a)):
import math
def factors(n):
i = 2
j = n
j_sqrt = math.isqrt(j)
while i <= j_sqrt:
if j % i == 0:
while j % i == 0:
j //= i
yield i
j_sqrt = math.isqrt(j)
i += 1 if i == 2 else 2
if j > 1:
yield j
def steps(a, b):
p, q = divmod(b, a)
if q == 0:
c = a
yield c
for f in factors(p):
c *= f
yield c
def main():
s = tuple(steps(*map(int, input().split())))
print(len(s) - 1, ':', ' -> '.join(map(str, s)))
main()
$ echo 2 144 | python bars.py 5 : 2 -> 4 -> 8 -> 16 -> 48 -> 144