Автор задачі: | Al_Kaosar |
Підготовлено: | MathModel |
Відредаговано: | MathModel |
Розв'язок
Мета полягає в мінімізації f(x, y) = |n - x^y| + |x - y| для x, y \ge 1.
Для фіксованого значення , при якому x^y є найближчим до , дорівнює або \lfloor n^{1/y} \rfloor, або \lceil n^{1/y} \rceil. Оскільки n \le 10^{18}, якщо x \ge 2, то може бути не більшим за приблизно , бо 2^{60} > 10^{18}. Якщо x=1, вираз набуває вигляду |n-1| + |1-y|, і його мінімум досягається при y=1, даючи значення n-1.
Можна перебрати всі можливі значення від до . Для кожного ми оцінюємо x \approx n^{1/y}. Через можливі проблеми з точністю чисел з плаваючою комою для n=10^{18} безпечніше знаходити за допомогою pow(n, 1/y) і потім перевіряти невеликий діапазон навколо нього, або використовувати бінарний пошук, щоб знайти таке, що x^y \le n.
Для кожного y \in [1, 62] ми перевіряємо x_{cand} \in \{\lfloor n^{1/y} \rfloor, \lceil n^{1/y} \rceil\}. Також перевіряємо кандидат x=y, оскільки тоді друга частина виразу дорівнює нулю.
Загальна складність становить O(\log n).
def solve():
n=int(input())
ans=n-1
K=n.bit_length()
for y in range(2,K+1):
r=int(n**(1/y))
for x in(r,r+1):
if x>0:
p=pow(x,y)
ans=min(ans,abs(n-p)+abs(x-y))
print(ans)
for _ in range(int(input())):
solve()