1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
| import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;
public class ExLucas {
public static Map<Integer, Integer> factorize(int p) { Map<Integer, Integer> factors = new HashMap<>(); for (int i = 2; i * i <= p; i++) { while (p % i == 0) { factors.put(i, factors.getOrDefault(i, 0) + 1); p /= i; } } if (p > 1) factors.put(p, 1); return factors; }
public static int factorialMod(int n, int p, int pk) { if (n == 0) return 1; int res = 1; for (int i = 1; i <= pk; i++) { if (i % p == 0) continue; res = (res * i) % pk; } res = powMod(res, n / pk, pk); for (int i = 1; i <= n % pk; i++) { if (i % p == 0) continue; res = (res * i) % pk; } return (res * factorialMod(n / p, p, pk)) % pk; }
public static int powMod(int base, int exp, int mod) { int result = 1; base = base % mod; while (exp > 0) { if (exp % 2 == 1) { result = (result * base) % mod; } exp = exp >> 1; base = (base * base) % mod; } return result; }
public static int countP(int n, int p) { int count = 0; while (n > 0) { n /= p; count += n; } return count; }
public static int combModPk(int n, int m, int p, int pk) { if (m > n) return 0; int num = factorialMod(n, p, pk); int den1 = factorialMod(m, p, pk); int den2 = factorialMod(n - m, p, pk); int den = (den1 * den2) % pk; int invDen = modInverse(den, pk); int powP = countP(n, p) - countP(m, p) - countP(n - m, p); return (num * invDen % pk * powMod(p, powP, pk)) % pk; }
public static int modInverse(int a, int m) { return powMod(a, m - 2, m); }
public static int crt(List<Integer> remainders, List<Integer> mods) { int M = 1; for (int mod : mods) { M *= mod; } int res = 0; for (int i = 0; i < remainders.size(); i++) { int mi = mods.get(i); int Mi = M / mi; int invMi = modInverse(Mi, mi); res = (res + remainders.get(i) * Mi % M * invMi % M) % M; } return res; }
public static int exLucas(int n, int m, int p) { Map<Integer, Integer> factors = factorize(p); List<Integer> remainders = new ArrayList<>(); List<Integer> mods = new ArrayList<>(); for (Map.Entry<Integer, Integer> entry : factors.entrySet()) { int prime = entry.getKey(); int exp = entry.getValue(); int pk = (int) Math.pow(prime, exp); int rem = combModPk(n, m, prime, pk); remainders.add(rem); mods.add(pk); } return crt(remainders, mods); }
public static void main(String[] args) { int n = 100; int m = 50; int p = 12; int result = exLucas(n, m, p); System.out.println("C(" + n + ", " + m + ") mod " + p + " = " + result); } }
|