Modular Inverse Fermat Little Theorem

/**
 * @file
 * @brief C++ Program to find the modular inverse using [Fermat's Little
 * Theorem](https://en.wikipedia.org/wiki/Fermat%27s_little_theorem)
 *
 * Fermat's Little Theorem state that \f[Ο•(m) = m-1\f]
 * where \f$m\f$ is a prime number.
 * \f{eqnarray*}{
 *  a \cdot x &≑& 1 \;\text{mod}\; m\\
 *  x &≑& a^{-1} \;\text{mod}\; m
 * \f}
 * Using Euler's theorem we can modify the equation.
 *\f[
 * a^{Ο•(m)} ≑ 1 \;\text{mod}\; m
 * \f]
 * (Where '^' denotes the exponent operator)
 *
 * Here 'Ο•' is Euler's Totient Function. For modular inverse existence 'a' and
 * 'm' must be relatively primes numbers. To apply Fermat's Little Theorem is
 * necessary that 'm' must be a prime number. Generally in many competitive
 * programming competitions 'm' is either 1000000007 (1e9+7) or 998244353.
 *
 * We considered m as large prime (1e9+7).
 * \f$a^{Ο•(m)} ≑ 1 \;\text{mod}\; m\f$ (Using Euler's Theorem)
 * \f$Ο•(m) = m-1\f$ using Fermat's Little Theorem.
 * \f$a^{m-1} ≑ 1 \;\text{mod}\; m\f$
 * Now multiplying both side by \f$a^{-1}\f$.
 * \f{eqnarray*}{
 * a^{m-1} \cdot a^{-1} &≑& a^{-1} \;\text{mod}\; m\\
 * a^{m-2} &≑&  a^{-1} \;\text{mod}\; m
 * \f}
 *
 * We will find the exponent using binary exponentiation. Such that the
 * algorithm works in \f$O(\log m)\f$ time.
 *
 * Examples: -
 * * a = 3 and m = 7
 * * \f$a^{-1} \;\text{mod}\; m\f$ is equivalent to
 * \f$a^{m-2} \;\text{mod}\; m\f$
 * * \f$3^5 \;\text{mod}\; 7 = 243 \;\text{mod}\; 7 = 5\f$
 * <br/>Hence, \f$3^{-1} \;\text{mod}\; 7 = 5\f$
 * or \f$3 \times 5  \;\text{mod}\; 7 = 1 \;\text{mod}\; 7\f$
 * (as \f$a\times a^{-1} = 1\f$)
 */

#include <iostream>
#include <vector>

/** Recursive function to calculate exponent in \f$O(\log n)\f$ using binary
 * exponent.
 */
int64_t binExpo(int64_t a, int64_t b, int64_t m) {
    a %= m;
    int64_t res = 1;
    while (b > 0) {
        if (b % 2) {
            res = res * a % m;
        }
        a = a * a % m;
        // Dividing b by 2 is similar to right shift.
        b >>= 1;
    }
    return res;
}

/** Prime check in \f$O(\sqrt{m})\f$ time.
 */
bool isPrime(int64_t m) {
    if (m <= 1) {
        return false;
    } else {
        for (int64_t i = 2; i * i <= m; i++) {
            if (m % i == 0) {
                return false;
            }
        }
    }
    return true;
}

/**
 * Main function
 */
int main() {
    int64_t a, m;
    // Take input of  a and m.
    std::cout << "Computing ((a^(-1))%(m)) using Fermat's Little Theorem";
    std::cout << std::endl << std::endl;
    std::cout << "Give input 'a' and 'm' space separated : ";
    std::cin >> a >> m;
    if (isPrime(m)) {
        std::cout << "The modular inverse of a with mod m is (a^(m-2)) : ";
        std::cout << binExpo(a, m - 2, m) << std::endl;
    } else {
        std::cout << "m must be a prime number.";
        std::cout << std::endl;
    }
}
Algerlogo

Β© Alger 2022

About us

We are a group of programmers helping each other build new things, whether it be writing complex encryption programs, or simple ciphers. Our goal is to work together to document and model beautiful, helpful and interesting algorithms using code. We are an open-source community - anyone can contribute. We check each other's work, communicate and collaborate to solve problems. We strive to be welcoming, respectful, yet make sure that our code follows the latest programming guidelines.