求组合数
Posted ignorance
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求组合数相关的知识,希望对你有一定的参考价值。
1 递推公式 Cb a = C b a-1 + Cb-1 a-1
时间复杂度 O(n2 +M )------ n是a,b的最大值,M是询问次数。
2.利用逆元求组合数取模(mod是质数用费马小定理)
预处理出阶乘和阶乘逆元 最后套公式求 Cb a
时间复杂度 O(M + nlog(n))
#include <iostream> #include <string> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <queue> #include <functional> #include <map> #include <set> #include <stack> #define FT(a, b) memset(a, b, sizeof(a)) #define FAT(a) memset(a, 0, sizeof(a)) using namespace std; typedef long long ll; const int M = 1e5 + 10; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int t; ll Factorial[M], InFactorial[M]; ll qpower(ll a, ll b) { ll res = 1; while (b) { if (b & 1) res = (res * a) % mod; a = a * a % mod; b >>= 1; } return res % mod; } int main() { #ifdef ONLINE_JUDGE #else freopen("/home/wjy/code/c++/in.txt", "r", stdin); #endif Factorial[0] = InFactorial[0] = 1; for (int i = 1; i < M; i++) { Factorial[i] = Factorial[i - 1] * i % mod; InFactorial[i] = InFactorial[i - 1] * qpower(i, mod - 2) % mod; } scanf("%d", &t); while (t--) { ll a, b; scanf("%lld%lld", &a, &b); printf("%lld ", ((Factorial[a] % mod * InFactorial[b]) % mod * InFactorial[a - b]) % mod); } return 0; }
3.Lucas 定理
Cb a ≡ Cb%p a%p * Cb/p a/p (mod p)
时间复杂度 : (M*logp N * log p *p)
#include <iostream> #include <string> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <queue> #include <functional> #include <map> #include <set> #include <stack> #define FT(a, b) memset(a, b, sizeof(a)) #define FAT(a) memset(a, 0, sizeof(a)) using namespace std; typedef long long ll; const int M = 1e5 + 10; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int t; ll p; ll qpower(ll a, ll b) { ll res = 1; while (b) { if (b & 1) res = (res * a) % p; a = a * a % p; b >>= 1; } return res % p; } ll C(ll a, ll b) { ll res = 1; for (int i = 1, j = a; i <= b; i++, j--) { res = res * j % p * qpower(i, p - 2) % p % mod; } return res; } ll lucas(ll a, ll b) { if (a < p && b < p) return C(a, b); else return C(a % p, b % p) * lucas(a / p, b / p) % p; } int main() { #ifdef ONLINE_JUDGE #else freopen("/home/wjy/code/c++/in.txt", "r", stdin); #endif scanf("%d", &t); while (t--) { ll a, b; scanf("%lld%lld%lld", &a, &b, &p); printf("%lld ", lucas(a, b)); } return 0; }
以上是关于求组合数的主要内容,如果未能解决你的问题,请参考以下文章