(5)ASP.NET Core3.1 Ocelot服務質量
阿新 • • 發佈:2020-11-12
\[C_m^n = \dfrac {m!} {n!(m-n)!} \]( 不是盧斯卡...
求組合數模數的方法
一般情況下對一個大素數 \(p\) 取模, 可以線性處理出階乘,階乘的逆元, \(O(1)\) 計算就可以。
const int N = 1e6 + 10; int fac[N],invfac[N],inv[N]; const int mod = 998244353; void init(){ fac[0] = invfac[0] = 1; fac[1] = invfac[1] = 1; inv[1] = 1; for(int i = 2;i < N;i++){ fac[i] = fac[i-1] * i % mod; inv[i] = (mod - mod / i)*inv[mod % i] % mod; invfac[i] = invfac[i-1] * inv[i] % mod; } } int C(int n,int m){ return fac[n]*invfac[n-m]*invfac[m]; }
但是, 當 \(p < m\) 的時候,就需要用 \(Lucas\) 了
\[C_m^n = C_{m\%p}^{n\%p} \cdot \ C_{m/p}^{n/p} \ \ (mod\ \ p) \]/* * @Author: zhl * @Date: 2020-11-12 10:27:57 */ #include<bits/stdc++.h> using ll = long long; using namespace std; const int N = 1e6 + 10; ll fac[N], invfac[N], inv[N]; void init(int n, int mod) { fac[0] = invfac[0] = 1; fac[1] = invfac[1] = 1; inv[1] = 1; for (int i = 2; i < n; i++) { fac[i] = fac[i - 1] * i % mod; inv[i] = (mod - mod / i) * inv[mod % i] % mod; invfac[i] = invfac[i - 1] * inv[i] % mod; } } // 需要先預處理出fact[],即階乘 ll C(ll m, ll n, ll p){ return m < n ? 0 : fac[m] * invfac[n] % p * invfac[m - n] % p; } ll lucas(ll m, ll n, ll p){ return n == 0 ? 1 % p : lucas(m / p, n / p, p) * C(m % p, n % p, p) % p; } int T, n, m, k; int main() { scanf("%d", &T); while (T--) { scanf("%d%d%d", &n, &m, &k); init(n + m + 1, k); printf("%lld\n", lucas(n + m, n, k)); } }