Легкий способ находить Обратное число по модулю

Revision ru1, by Forestmy17, 2026-04-28 22:38:24

Возможно, вы всё ещё используете малую теорему Ферма, чтобы находить обратные элементы по модулю простого числа $$$p$$$.

Если p — простое число и x не делится на p, то по малой теореме Ферма:

$$$x^{p-1}\equiv 1\pmod p$$$

Следовательно,

$$$x^{p-2}\equiv x^{-1}\pmod p$$$

Поэтому стандартный способ найти обратный элемент — использовать бинарное возведение в степень:

int binpow(int a, int n) {
    int res = 1;
    while (n) {
        if (n&1) res = 1LL * res * a % mod;
        a = 1LL * a * a % mod;
        n >>= 1;
    }
    return res;
}
int inv(int x) {
    return binpow(x, mod - 2);
}

Этот способ отлично работает. Но для такой частой операции хочется иметь что-то короче.

Например, обратный элемент можно записать так:

int inv(int x) {
    return x == 1 ? 1 : mod - 1LL * (mod / x) * inv(mod % x) % mod;
}

Теперь докажем, почему эта формула работает.

Сначала запишем mod через деление с остатком:

$$$mod = (mod / x) * x + mod \% x$$$

Следовательно,

$$$mod \% x = mod - (mod / x) * x$$$

Так как мы работаем по модулю mod, значение mod сравнимо с 0, поэтому:

$$$mod \% x\equiv -(mod/x) * x \pmod{mod}$$$

Теперь умножим обе части на $$$inv(mod\%x)$$$

Unable to parse markup [type=CF_MATHJAX]

(mod \% x) * inv(mod \% x) \equiv 1 \pmod{mod}\big)$:
$$$1\equiv -(mod / x) * x * inv(mod \% x) \pmod{mod}$$$

Так как mod — простое число и x не делится на mod, то деление на x корректно по модулю mod.

Разделив обе части на x, получаем:

$$$x^{-1} \equiv -(mod / x) * inv(mod \% x) \pmod{mod}$$$

Но $$$x^{-1}$$$ — это обратный элемент к x, поэтому:

$$$inv(x) \equiv -(mod / x) * inv(mod \% x) \pmod{mod}$$$

Конечно, мы хотим получить неотрицательное значение, поэтому вместо того, чтобы возвращать отрицательное число напрямую, добавим mod:

$$$inv(x) \equiv mod - (mod / x) * inv(mod \% x) \pmod{mod}$$$

Так мы получили рекурсивную формулу:

int inv(int x) {
    return x == 1 ? 1 : mod - 1LL * (mod / x) * inv(mod % x) % mod;
}

Рекурсия останавливается при x = 1, потому что inv(1) = 1.

Сложность — $$$O(\log mod)$$$, как и в первом решении, но реализация получается гораздо короче, чем бинарное возведение в степень.

History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
ru2 Russian Forestmy17 2026-04-28 22:40:00 2 Мелкая правка: '%x)$ $\big($мы знаем, ' -> '%x)$ $\big ($ мы знаем, '
ru1 Russian Forestmy17 2026-04-28 22:38:24 2349 Первая редакция перевода на Русский
en1 English Forestmy17 2026-04-28 22:31:56 2269 Initial revision (published)