Вычисление специального факториала по модулю p за O(p log N) | OTUS
⚡ Подписка на курсы OTUS!
Интенсивная прокачка навыков для IT-специалистов!
Подробнее

Курсы

Программирование
Backend-разработчик на PHP
-9%
Алгоритмы и структуры данных
-9%
Team Lead
-6%
Архитектура и шаблоны проектирования Разработчик IoT
-13%
C# Developer. Professional
-9%
HTML/CSS
-11%
C# ASP.NET Core разработчик
-5%
Kotlin Backend Developer
-8%
iOS Developer. Professional
-8%
Java Developer. Professional JavaScript Developer. Professional Базы данных Android Developer. Professional Framework Laravel Cloud Solution Architecture Highload Architect Reverse-Engineering. Professional Vue.js разработчик Agile Project Manager VOIP инженер Scala-разработчик Супер-практикум по использованию и настройке GIT Symfony Framework Java Developer. Basic Unity Game Developer. Professional Супер-интенсив Azure
Инфраструктура
Экспресс-курс «IaC Ansible»
-10%
Administrator Linux.Basic
-10%
Мониторинг и логирование: Zabbix, Prometheus, ELK
-10%
Экспресс-курс «CI/CD или Непрерывная поставка с Docker и Kubernetes»
-30%
Administrator Linux. Professional
-6%
Дизайн сетей ЦОД
-13%
NoSQL Основы Windows Server MS SQL Server Developer Инфраструктурная платформа на основе Kubernetes Cloud Solution Architecture Highload Architect Разработчик голосовых ассистентов и чат-ботов VOIP инженер Супер-практикум по работе с протоколом BGP Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes Супер-интенсив "Tarantool"
Специализации Курсы в разработке Подготовительные курсы
+7 499 938-92-02

Вычисление специального факториала по модулю p за O(p log N)

Algo_Deep_3.07_site-5020-580834.png

Рассмотрим задачу вычисления формул, состоящих из дробей, где в числителе и в знаменателе присутствуют факториалы (например, биномиальные коэффициенты).

Будем вычислять факториалы по некоторому небольшому простому модулю p, пропуская сами множители p, потому что в дробях множители p сократятся, и результат будет взят по модулю p.

1-20219-6972b4.jpgВидно, что формула делится на несколько блоков одинаковой длины, за исключением последней части:

2-20219-6ec404.jpgОдинаковые блоки содержат общую часть (p - 1)! mod p, что по теореме Вильсона равно p - 1. Чтобы перемножить эти общие части, p - 1 нужно возвести в степень по модулю p (как рассказывается в нашей статье «Быстрое возведение в степень»), однако результат всегда будет 1 или p - 1 в зависимости от чётности показателя.

Значение последнего блока можно вычислить отдельно за O(p). Рассмотрим последние элементы блоков:

3-20219-99db08.jpg

Задача свелась к задаче меньшей размерности (осталось n / p блоков). 4-20219-17b366.jpgПрограмма:

    def factmod(n, p):
        res = 1
        while n > 1:
            res = (res * (p - 1 if int(n / p) % 2 else 1)) % p
            for i in range(2, n % p + 1):
                res = (res * i) % p  
            n = int(n / p)
        return res % p

Есть вопросы? Напишите в комментариях!

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться