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 118 119 120 121 122 123 124 125
|
const int MAX = 1000005; const int MOD = 999983;
pair<int, int> divisors[128]; int prime_divisors(int x) { int cnt = 0; for (int i = 2; i <= x / i; i++) if (x % i == 0) { divisors[cnt] = {i, 0}; while (x % i == 0) { x /= i; divisors[cnt].second++; } cnt++; } if (x > 1) divisors[cnt++] = {x, 1}; return cnt; }
int fac[MAX]; int cnt_divisors; void init_exLucas() { fac[0] = 1; for (int i = 1; i <= MOD; i++) fac[i] = fac[i - 1] * i % MOD; cnt_divisors = prime_divisors(MOD); }
int quick_pow(int base, int exponent) { __int128_t res = 1; while (exponent) { if (exponent & 1) res *= base; base *= base; exponent >>= 1; } return res; } int quick_pow(int base, int exponent, int modulo) { int res = 1 % modulo; base %= modulo; while (exponent) { if (exponent & 1) res = res * base % modulo; base = base * base % modulo; exponent >>= 1; } return res; }
int _exgcd(int a, int b, int &x, int &y) { int d = a; if (b != 0) { d = _exgcd(b, a % b, y, x); y -= (a / b) * x; } else { x = 1; y = 0; } return d; } inline bool exgcd(int a, int b, int c, int &x, int &y) { int _x, _y, g; g = _exgcd(a, b, _x, _y); if (c % g) return false; int p = b / g; x = (c / g * _x % p + p) % p; y = (c - a * x) / b; return true; }
inline int linear_congruence_theorem(int a, int c, int m) { int x, y; bool flag = exgcd(a, m, c, x, y); return flag ? x : -1; }
inline int inv(int primal, int modulo) { return linear_congruence_theorem(primal, 1, modulo); }
int CRT(int rest[], int modulo[], int n) { int res = 0, M = MOD; for (int i = 0; i < n; i++) { int mi = modulo[i], Mi = M / mi; res = (res + rest[i] * Mi * inv(Mi % mi, mi)) % M; } return res; }
int exLucas(int m, int n) { if (n < 0 or n > m) return 0; static int rest[128], modulo[128]; for (int i = 0; i < cnt_divisors; i++) { int p = divisors[i].first, M = quick_pow(p, divisors[i].second); int cnt = 0, R = 1; for (int i = m; i; i /= p) { cnt += i / p; R = R * fac[i % p] % M; } for (int i = n; i; i /= p) { cnt -= i / p; R = R * inv(fac[i % p], M) % M; } for (int i = m - n; i; i /= p) { cnt -= i / p; R = R * inv(fac[i % p], M) % M; } R = R * quick_pow(fac[p], cnt, M) % M; rest[i] = R; modulo[i] = M; } return CRT(rest, modulo, cnt_divisors); }
|