Kaosar və Minimallaşdırma#12437

Kaosar və Minimallaşdırma (Həll təhlili)

Məsələnin müəllifi:

Al_Kaosar

Hazırlayan:

MathModel

Redaktə edən:

MathModel

Həll

Məqsəd x, y \ge 1 üçün f(x, y) = |n - x^y| + |x - y| ifadəsini minimum etməkdir.

Sabit üçün x^y qiymətini -ə ən yaxın edən ya \lfloor n^{1/y} \rfloor, ya da \lceil n^{1/y} \rceil olur. n \le 10^{18} olduğuna görə, əgər x \ge 2-dirsə, onda ən çox təxminən ola bilər, çünki 2^{60} > 10^{18}. Əgər x=1 olarsa, ifadə |n-1| + |1-y| şəklini alır və bu da y=1 olduqda minimum olur, nəticə isə n-1 edir.

Biz -nin bütün mümkün qiymətlərini -dən -yə qədər yoxlaya bilərik. Hər bir üçün x \approx n^{1/y} qiymətini təxmin edirik. n=10^{18} üçün üzən nöqtəli hesablamalarda dəqiqlik problemləri yarana biləcəyindən, -i pow(n, 1/y) ilə tapıb onun ətrafında kiçik bir aralığı yoxlamaq, yaxud x^y \le n şərtini ödəyən -i tapmaq üçün ikili axtarışdan istifadə etmək daha təhlükəsizdir.

Hər bir y \in [1, 62] üçün x_{cand} \in \{\lfloor n^{1/y} \rfloor, \lceil n^{1/y} \rceil\} namizədlərini yoxlayırıq. Həmçinin x=y namizədini də yoxlayırıq, çünki bu halda ifadənin ikinci hissəsi sıfır olur.

Ümumi mürəkkəblik O(\log n)-dir.

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