Kaosar і мінімізація#12437

Kaosar і мінімізація (Розбір)

Автор задачі:

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()