Автор проблеми: | AlKaosar Hussain |
Підготовлено: | Hasan Saleh (MathModel) |
Редагував: | Hasan Saleh (MathModel) |
Рішення Ми беремо числа
і хочемо
Чистий спосіб зробити це - подивитися на це простими числами. Нехай
буде простим розкладом . НСД біноміальних коефіцієнтів також буде дільником , отже, він матиме форму
для деяких f_p \le e_p. Наша задача - знайти для кожного простого числа , яке ділить , яка найменша степінь , що з'являється в усіх
Ця "найменша степінь" є точною
але ніколи не від'ємною (якщо вона стає від'ємною, ми просто ставимо ).
Чому це правда? Фіксуємо просте число і припустимо, що має -адичну оцінку , тобто n = p^e \cdot r з \gcd(r,p)=1. Тепер подивіться на біноміальний коефіцієнт з k = p^t, де
Цей знаходиться в нашому діапазоні 1 \le k \le m. Для цього спеціального можна перевірити (це стандартний факт і може бути доведено з перенесеннями в основі або шляхом розгляду факторіалів), що
Отже, для цього конкретного степінь всередині \binom{n}{k} є точною p^{e-t}. Це вже показує, що НСД не може мати більше, ніж p^{e-t}.
Друга частина полягає в тому, що для будь-якого k \le m ви не можете отримати меншу степінь , ніж e - t. Інтуїтивно: щоб "вбити" більше степенів в біноміальному коефіцієнті, повинен містити більше факторів в , але до ви можете отримати максимум \lfloor \log_p m \rfloor факторів з знаменника, тому показник у біноміальному коефіцієнті залишається \ge e - \lfloor \log_p m \rfloor. Отже, мінімум для всіх k \in [1,m] є точно
Збираючи це разом для всіх простих чисел, що ділять , ми отримуємо
Код робить саме це:
розкладає на прості числа з показниками ;
для кожного обчислює \texttt{flog}(m,p), що буквально є
шляхом повторного ділення на ;
якщо e > \texttt{flog}(m,p), ми множимо відповідь на p^{e-\texttt{flog}(m,p)}.
Складність становить \mathcal{O}(\sqrt{n}).
def flog(m,p):
t=0
while m>=p:
m//=p
t+=1
return t
def g(n,m):
ans=1;x=n;i=2
while i*i<=x:
e=0
while x%i==0:
x//=i
e+=1
if e:
t=flog(m,i)
if e>t: ans*=i**(e-t)
i+=1
if x>1:
t=flog(m,x)
if 1>t: ans*=x**(1-t)
return ans
for _ in range(int(input())):
n,m=map(int,input().split())
print(g(n,m))