标签:lse pen sizeof max 分享 方案 img lin ini
C(n, m) 代表 从 n 个物品中取 m 个的方案数
1、n ≤ 1e3 、m ≤ 1e3
利用组合递推公式打表就行了
const int C_maxn = 1e3 + 10; LL Comb[maxn][maxn]; inline void Comb_init() { for(int i=1; i<C_maxn; i++){ Comb[i][0] = 1; Comb[i][i] = 1; for(int j=1; j<C_maxn; j++){ Comb[i][j] = Comb[i][j-1] + Comb[i-1][j-1]; //Comb[i][j] = (Comb[i][j-1] + Comb[i-1][j-1]) % mod; } } }
2、n ≤ 1e6、m ≤ 1e6 、模数 mod 为素数的情况下
预处理阶乘极其逆元
const int Comb_Maxn = 1e5 + 10; LL Fac_inv[Comb_Maxn]; LL Fac[Comb_Maxn]; inline void Comb_init() { Fac_inv[0] = Fac[0] = 1; Fac_inv[1] = 1; for(int i=1; i<Comb_Maxn; i++) Fac[i] = Fac[i-1] * (LL)i % mod; for(int i=2; i<Comb_Maxn; i++) Fac_inv[i] = (LL)(mod - mod / i) * Fac_inv[mod % i] % mod; for(int i=1; i<Comb_Maxn; i++) Fac_inv[i] = Fac_inv[i-1] * Fac_inv[i] % mod; } LL Comb(int n, int m) { return Fac[n] * Fac_inv[m] % mod * Fac_inv[n-m] % mod; }
3、n ≤ 1e18、m ≤ 1e18 、模数 mod 为素数的情况下
利用卢卡斯定理
LL pow_mod(LL a, LL b, LL p) { LL res = 1; while(b != 0){ if(b&1) res = (res * a) % p; a = (a*a) % p; b >>= 1; } return res; } LL Comb(LL a, LL b, LL p) { if(a < b) return 0; if(a == b) return 1; if(b > a - b) b = a - b; LL ans = 1, ca = 1, cb = 1; for(LL i = 0; i < b; ++i) { ca = (ca * (a - i))%p; cb = (cb * (b - i))%p; } ans = (ca*pow_mod(cb, p - 2, p)) % p; return ans; } LL Lucas(LL n,LL m,LL p) { LL ans = 1; while(n&&m&&ans){ ans = (ans*Comb(n%p, m%p, p)) % p; n /= p; m /= p; } return ans; }
如果 mod 数小一点、可预处理阶乘逆元
const int P_maxn = 10005; bool isPrime[P_maxn]; int prime[P_maxn],fac[P_maxn][P_maxn],inv[P_maxn][P_maxn],cnt,pth[P_maxn]; void prime_init(){ cnt=0; memset(isPrime,true,sizeof(isPrime)); for(int i=2;i<P_maxn;i++){ if(isPrime[i]){ prime[++cnt]=i; pth[i]=cnt; for(int j=i+i;j<P_maxn;j+=i) isPrime[j]=0; } } } int quick_mod(int a, int b, int p){ a %= p; int ret = 1; while(b){ if(b & 1){ ret = ret * a % p; b--; } b>>=1; a = a * a % p; } return ret; } void inv_init(){//预处理阶乘与逆元 int i,j; for(int i=1;i<=cnt;i++){ fac[i][0]=inv[i][0]=1; for(int j=1;j<prime[i];j++){ fac[i][j] = (fac[i][j-1] * j) % prime[i]; inv[i][j] = quick_mod(fac[i][j], prime[i]-2, prime[i]); } } } int Comb(int n,int m,int P){ if(m>n) return 0; if(m==n) return 1; int t=pth[P]; return fac[t][n]*(inv[t][n-m]*inv[t][m]%P)%P; } int Lucas(int n,int m,int P){ if(m==0) return 1; return Comb(n%P, m%P, P) * Lucas(n/P, m/P, P)%P; }
4、n ≤ 1e6、m ≤ 1e6 、模数 mod 可能为合数的情况下
const int P_maxn = 200005; bool isPrime[P_maxn]; int prime[P_maxn]; int cnt; void prime_init() { cnt = 0; memset(isPrime,true,sizeof(isPrime)); for(int i=2; i<P_maxn; i++) { if(isPrime[i]) { prime[cnt++] = i; for(int j=i+i; j<P_maxn; j+=i) isPrime[j] = false; } } } LL quick_mod(LL a,LL b,LL m) { LL ans = 1; a %= m; while(b) { if(b & 1) { ans = ans * a % m; b--; } b >>= 1; a = a * a % m; } return ans; } LL Work(LL n,LL p) { LL ans = 0; while(n) { ans += n / p; n /= p; } return ans; } LL Solve(LL n,LL m,LL P) { LL ans = 1; for(int i=0; i<cnt && prime[i]<=n; i++) { LL x = Work(n, prime[i]); LL y = Work(n - m, prime[i]); LL z = Work(m, prime[i]); x -= (y + z); ans *= quick_mod(prime[i], x, P); ans %= P; } return ans; } int main() { prime_init(); LL n,m,P; cin>>n>>m>>P; cout<<Solve(n,m,P)<<endl; return 0; }
标签:lse pen sizeof max 分享 方案 img lin ini
原文地址:https://www.cnblogs.com/Rubbishes/p/9468855.html