Fermat's Little Theorem Explained

Fermat's Little Theorem

Fermat's Little Theorem states that if p is a prime number and a is an integer such that p does not divide a, then:

ap-1 ≡ 1 (mod p)

A practical use of this theorem is in computing modular inverses and modular exponentiation efficiently, especially in number theory and cryptography.

Algorithm

To compute ap-2 mod p, we use binary exponentiation:

 
modular_pow(a, b, p):
    result = 1
    a = a % p
    while b > 0:
        if b % 2 == 1:
            result = (result * a) % p
        a = (a * a) % p
        b = b // 2
    return result
 

Time and Space Complexity

  • Time Complexity: O(log b) for exponentiation
  • Space Complexity: O(1)

Easy Problems

1. Compute ab mod p

 
// C++
#include <iostream>
using namespace std;

long long mod_pow(long long a, long long b, long long p) {
    long long res = 1;
    a = a % p;
    while (b > 0) {
        if (b % 2 == 1)
            res = (res * a) % p;
        a = (a * a) % p;
        b /= 2;
    }
    return res;
}

int main() {
    cout << mod_pow(3, 200, 13) << endl; // Output: 9
    return 0;
}
    

2. Modular Inverse of a number mod p

// C++
#include <iostream>
using namespace std;

long long mod_inverse(long long a, long long p) {
    return mod_pow(a, p - 2, p);
}

int main() {
    long long a = 3, p = 11;
    cout << mod_inverse(a, p) << endl; // Output: 4
    return 0;
}

Intermediate Problems

1. Calculate nCr % p (p is prime)


// C++
#include <iostream>
using namespace std;

const int MAX = 1000;
long long fact[MAX];

long long mod_pow(long long a, long long b, long long p) {
    long long res = 1;
    a %= p;
    while (b) {
        if (b % 2) res = (res * a) % p;
        a = (a * a) % p;
        b /= 2;
    }
    return res;
}

void compute_factorials(int p) {
    fact[0] = 1;
    for (int i = 1; i < MAX; ++i)
        fact[i] = (fact[i - 1] * i) % p;
}

long long nCr_mod_p(int n, int r, int p) {
    if (r > n) return 0;
    compute_factorials(p);
    long long num = fact[n];
    long long denom = (fact[r] * fact[n - r]) % p;
    return (num * mod_pow(denom, p - 2, p)) % p;
}

int main() {
    cout << nCr_mod_p(10, 3, 13) << endl; // Output: 3
    return 0;
}
 

2. Check if a number is a Fermat pseudoprime to base a


// C++
#include <iostream>
using namespace std;

bool is_fermat_pseudoprime(int n, int a) {
    if (n <= 1 || n == a) return false;
    return mod_pow(a, n - 1, n) == 1;
}

int main() {
    cout << is_fermat_pseudoprime(561, 2) << endl; // Output: 1 (true)
    return 0;
}
    

Hard Problem

Modular Inverse for an Array under Modulo p (where p is prime)

Precompute modular inverses for all numbers from 1 to N efficiently using Fermat's Little Theorem.

// C++
#include <iostream>
#include <vector>
using namespace std;

vector<long long> compute_mod_inverses(int n, int p) {
    vector<long long> inv(n + 1);
    inv[1] = 1;
    for (int i = 2; i <= n; ++i) {
        inv[i] = mod_pow(i, p - 2, p);
    }
    return inv;
}

int main() {
    int n = 10, p = 13;
    vector<long long> inv = compute_mod_inverses(n, p);
    for (int i = 1; i <= n; ++i) {
        cout << "Inverse of " << i << " mod " << p << " is " << inv[i] << endl;
    }
    return 0;
}