Знаходження степеня дільника факторіала
Задано два числа і . Знайти найбільше ціле , таке що ділить .
- Чи потрібно знайти, у якому степені дільник (або просте ) входить у — без обчислення самого факторіала?
- Чи величезне (так, що неможливо обчислити прямо), а ви хочете відповідь за через формулу Лежандра?
- Якщо натомість потрібне саме значення — (→ Факторіал за модулем p)?
Просте
Спочатку розглянемо випадок простого . Явний вираз для факторіала має вигляд
Зауважимо, що кожен -тий елемент добутку ділиться на , тобто додає до відповіді; кількість таких елементів дорівнює .
Далі, кожен -тий елемент ділиться на , тобто додає ще до відповіді (перший степінь ми вже врахували в попередньому абзаці). Кількість таких елементів дорівнює .
І так далі: для кожного кожен -тий елемент додає ще до відповіді, і таких елементів є .
Остаточна відповідь дорівнює
Цей результат також відомий як формула Лежандра. Сума, звісно, скінченна, бо лише приблизно перші доданків не є нулями. Отже, час роботи цього алгоритму становить .
Реалізація
- C++
- Python
- TypeScript
- Go
int fact_pow (int n, int k) {
int res = 0;
while (n) {
n /= k;
res += n;
}
return res;
}
def fact_pow(n: int, k: int) -> int:
res = 0
while n:
n //= k # цілочисельне ділення
res += n
return res
function factPow(n: number, k: number): number {
let res = 0;
while (n) {
n = Math.floor(n / k); // цілочисельне ділення
res += n;
}
return res;
}
func factPow(n, k int) int {
res := 0
for n != 0 {
n /= k // цілочисельне ділення для int
res += n
}
return res
}
Складене
Цю саму ідею не можна застосувати безпосередньо. Натомість ми можемо розкласти на множники, подавши його у вигляді . Для кожного ми знаходимо, скільки разів він входить у , за допомогою описаного вище алгоритму — назвемо це значення . Відповідь для складеного буде