Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ $ java -cp classes com.williamfiset.algorithms.search.BinarySearch

# Mathematics

- [[UNTESTED] Chinese remainder theorem](src/main/java/com/williamfiset/algorithms/math/ChineseRemainderTheorem.java)
- [Chinese remainder theorem](src/main/java/com/williamfiset/algorithms/math/ChineseRemainderTheorem.java)
- [Prime number sieve (sieve of Eratosthenes)](src/main/java/com/williamfiset/algorithms/math/SieveOfEratosthenes.java) **- O(nlog(log(n)))**
- [Prime number sieve (sieve of Eratosthenes, compressed)](src/main/java/com/williamfiset/algorithms/math/CompressedPrimeSieve.java) **- O(nlog(log(n)))**
- [Totient function (phi function, relatively prime number count)](src/main/java/com/williamfiset/algorithms/math/EulerTotientFunction.java) **- O(√n)**
Expand All @@ -248,9 +248,9 @@ $ java -cp classes com.williamfiset.algorithms.search.BinarySearch
- [Fast Fourier transform (quick polynomial multiplication)](src/main/java/com/williamfiset/algorithms/math/FastFourierTransform.java) **- O(nlog(n))**
- [Fast Fourier transform (quick polynomial multiplication, complex numbers)](src/main/java/com/williamfiset/algorithms/math/FastFourierTransformComplexNumbers.java) **- O(nlog(n))**
- [Primality check](src/main/java/com/williamfiset/algorithms/math/PrimalityCheck.java) **- O(√n)**
- [Primality check (Rabin-Miller)](src/main/java/com/williamfiset/algorithms/math/RabinMillerPrimalityTest.py) **- O(k)**
- [Least Common Multiple (LCM)](src/main/java/com/williamfiset/algorithms/math/Lcm.java) **- ~O(log(a + b))**
- [Modular inverse](src/main/java/com/williamfiset/algorithms/math/ModularInverse.java) **- ~O(log(a + b))**
- [Modular exponentiation](src/main/java/com/williamfiset/algorithms/math/ModPow.java) **- O(log(n))**
- [Prime factorization (pollard rho)](src/main/java/com/williamfiset/algorithms/math/PrimeFactorization.java) **- O(n<sup>1/4</sup>)**
- [Relatively prime check (coprimality check)](src/main/java/com/williamfiset/algorithms/math/RelativelyPrime.java) **- ~O(log(a + b))**

Expand Down
7 changes: 0 additions & 7 deletions src/main/java/com/williamfiset/algorithms/math/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,6 @@ java_binary(
runtime_deps = [":math"],
)

# bazel run //src/main/java/com/williamfiset/algorithms/math:NChooseRModPrime
java_binary(
name = "NChooseRModPrime",
main_class = "com.williamfiset.algorithms.math.NChooseRModPrime",
runtime_deps = [":math"],
)

# bazel run //src/main/java/com/williamfiset/algorithms/math:PrimeFactorization
java_binary(
name = "PrimeFactorization",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* Computes the binomial coefficient C(n, r) mod p using Fermat's Little Theorem.
*
* Given a prime p, the binomial coefficient C(n, r) = n! / (r! * (n-r)!) can be computed modulo p
* by precomputing factorials mod p and using modular inverses for the denominator. Fermat's Little
* Theorem gives a^(p-1) ≡ 1 (mod p) for prime p, so the modular inverse of x is x^(p-2) mod p.
* Here we use the extended Euclidean algorithm via ModularInverse instead.
*
* Requires p to be prime so that modular inverses exist for all non-zero values mod p, and n < p
* so that factorials are non-zero mod p.
*
* Time Complexity: O(n) for factorial precomputation, O(log(p)) for each modular inverse.
*
* @author Rohit Mazumder, mazumder.rohit7@gmail.com
*/
package com.williamfiset.algorithms.math;

public class BinomialCoefficientModPrime {

/**
* Computes C(n, r) mod p.
*
* @param n total items (must be >= 0 and < p).
* @param r items to choose (must be >= 0 and <= n).
* @param p a prime modulus.
* @return C(n, r) mod p.
* @throws IllegalArgumentException if parameters are out of range.
*/
public static long compute(int n, int r, int p) {
if (n < 0 || r < 0 || r > n)
throw new IllegalArgumentException("Requires 0 <= r <= n, got n=" + n + ", r=" + r);
if (p <= 1)
throw new IllegalArgumentException("Modulus p must be > 1, got p=" + p);

if (r == 0 || r == n)
return 1;

long[] factorial = new long[n + 1];
factorial[0] = 1;
for (int i = 1; i <= n; i++)
factorial[i] = factorial[i - 1] * i % p;

return factorial[n]
% p * ModularInverse.modInv(factorial[r], p)
% p * ModularInverse.modInv(factorial[n - r], p)
% p;
}
}
Loading
Loading