Skip to content

Commit a884100

Browse files
committed
Add N choose R mod prime
1 parent 6586caf commit a884100

File tree

1 file changed

+59
-0
lines changed

1 file changed

+59
-0
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.williamfiset.algorithms.math;
2+
3+
import java.math.BigInteger;
4+
5+
public class NChooseRModPrime {
6+
/**
7+
* Calculate the value of C(N, R) % P using Fermat's Little Theorem.
8+
*
9+
* @param N
10+
* @param R
11+
* @param P
12+
* @return The value of N choose R Modulus P
13+
*/
14+
public static long compute(int N, int R, int P) {
15+
if (R == 0) return 1;
16+
17+
long[] factorial = new long[N + 1];
18+
factorial[0] = 1;
19+
20+
for (int i = 1; i <= N; i++) {
21+
factorial[i] = factorial[i - 1] * i % P;
22+
}
23+
24+
return (factorial[N]
25+
* ModularInverse.modInv(factorial[R], P)
26+
% P
27+
* ModularInverse.modInv(factorial[N - R], P)
28+
% P)
29+
% P;
30+
}
31+
32+
private static String bigIntegerNChooseRModP(int N, int R, int P) {
33+
if (R == 0) return "1";
34+
BigInteger num = new BigInteger("1");
35+
BigInteger den = new BigInteger("1");
36+
while (R > 0) {
37+
num = num.multiply(new BigInteger("" + N));
38+
den = den.multiply(new BigInteger("" + R));
39+
BigInteger gcd = num.gcd(den);
40+
num = num.divide(gcd);
41+
den = den.divide(gcd);
42+
N--;
43+
R--;
44+
}
45+
num = num.divide(den);
46+
num = num.mod(new BigInteger("" + P));
47+
return num.toString();
48+
}
49+
50+
public static void main(String args[]) {
51+
int N = 500;
52+
int R = 250;
53+
int P = 1000000007;
54+
int expected = Integer.parseInt(bigIntegerNChooseRModP(N, R, P));
55+
long actual = compute(N, R, P);
56+
System.out.println(expected); // 515561345
57+
System.out.println(actual); // 515561345
58+
}
59+
}

0 commit comments

Comments
 (0)