Перейти до основного вмісту

Знаходження степеня дільника факторіала

Задано два числа nn і kk. Знайти найбільше ціле xx, таке що kxk^x ділить n!n!.

Коли підходить цей алгоритм?
  • Чи потрібно знайти, у якому степені дільник kk (або просте pp) входить у n!n! — без обчислення самого факторіала?
  • Чи nn величезне (так, що n!n! неможливо обчислити прямо), а ви хочете відповідь за O(log⁡kn)O(\log_k n) через формулу Лежандра?
  • Якщо натомість потрібне саме значення n! mod pn! \bmod p — (→ Факторіал за модулем p)?

Просте kk​

Спочатку розглянемо випадок простого kk. Явний вираз для факторіала має вигляд

n!=1⋅2⋅3…(n−1)⋅nn! = 1 \cdot 2 \cdot 3 \ldots (n-1) \cdot n

Зауважимо, що кожен kk-тий елемент добутку ділиться на kk, тобто додає +1+1 до відповіді; кількість таких елементів дорівнює ⌊nk⌋\Bigl\lfloor\dfrac{n}{k}\Bigr\rfloor.

Далі, кожен k2k^2-тий елемент ділиться на k2k^2, тобто додає ще +1+1 до відповіді (перший степінь kk ми вже врахували в попередньому абзаці). Кількість таких елементів дорівнює ⌊nk2⌋\Bigl\lfloor\dfrac{n}{k^2}\Bigr\rfloor.

І так далі: для кожного ii кожен kik^i-тий елемент додає ще +1+1 до відповіді, і таких елементів є ⌊nki⌋\Bigl\lfloor\dfrac{n}{k^i}\Bigr\rfloor.

Остаточна відповідь дорівнює

⌊nk⌋+⌊nk2⌋+…+⌊nki⌋+…\Bigl\lfloor\dfrac{n}{k}\Bigr\rfloor + \Bigl\lfloor\dfrac{n}{k^2}\Bigr\rfloor + \ldots + \Bigl\lfloor\dfrac{n}{k^i}\Bigr\rfloor + \ldots

Цей результат також відомий як формула Лежандра. Сума, звісно, скінченна, бо лише приблизно перші log⁡kn\log_k n доданків не є нулями. Отже, час роботи цього алгоритму становить O(log⁡kn)O(\log_k n).

Реалізація​


int fact_pow (int n, int k) {
int res = 0;
while (n) {
n /= k;
res += n;
}
return res;
}

Складене kk​

Цю саму ідею не можна застосувати безпосередньо. Натомість ми можемо розкласти kk на множники, подавши його у вигляді k=k1p1⋅…⋅kmpmk = k_1^{p_1} \cdot \ldots \cdot k_m^{p_m}. Для кожного kik_i ми знаходимо, скільки разів він входить у n!n!, за допомогою описаного вище алгоритму — назвемо це значення aia_i. Відповідь для складеного kk буде

min⁡i=1…maipi\min_ {i=1 \ldots m} \dfrac{a_i}{p_i}