组合计数(1)
#include <iostream>
using namespace std;
// http://t.csdn.cn/VpZeL
// 适合处理c(a,b)数据量大、但a 和 b 数值较小的,用组合数数组预处理
const int N = 2010, mod = 1e9 + 7;
int c[N][N]; // c[i][j]表示 C i取j
// 预处理组合数数组
void init_C()
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j <= i; j++)
{
if (j == 0 || i == j)
{
c[i][j] = 1;
}
else
{
// 答案很大时模掉一个指定数
c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
}
}
}
}
int main()
{
init_C();
return 0;
}
组合计数(2)
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 100010, mod = 10e9 + 7;
// 使用公式 c(a,b) = a! / ((a-b)! * b!)
// 适合a和b数值比较大的
int fact[N], infact[N];// fact[i] 表示i的阶乘 % mod
// infact[i] 表示i的阶乘的逆 % mod
// 快速幂
int qmi(int a, int k, int p)
{
int res = 1;
while (k)
{
if (k & 1)
{
res = (LL)res * a % p;
}
a = (LL)a * a % p;
k = k >> 1;
}
return res;
}
int main()
{
fact[0] = infact[0] = 1;
for (int i = 1; i < N; i++)
{
fact[i] = (LL)fact[i - 1] * i % mod;
// 快速幂求逆元
infact[i] = (LL)infact[i - 1] * qmi(i, mod - 2, mod) % mod;
}
int a, b;
cin >> a >> b;
// 按照公式计算结果
cout << (LL)fact[a] * infact[b] % mod * infact[a - b] % mod;
return 0;
}
组合计数(3)
#include <iostream>
using namespace std;
// a和b的数值特别大,求出 C(a, b) % mod 的结果
// 卢卡斯定理:C(a,b) 同余于 C(a % mod, b % mod) * C(a / mod, b / mod)
typedef long long LL;
const int mod = 10e5 + 5;
// a b 的范围为0 ~ 10^18
// 快速幂
int qmi(int a, int k, int p)
{
int res = 1;
while (k)
{
if (k & 1)
{
res = (LL)res * a % p;
}
a = (LL)a * a % p;
k = k >> 1;
}
return res;
}
// 使用组合计数(2)的方法计算
int C(int a, int b)
{
int res = 1;
for (int i = 1, j = a; i <= b; i++, j--)
{
res = (LL)res * j % mod;
res = (LL)res * qmi(i, mod - 2, mod) % mod;
}
return res;
}
// 卢卡斯定理实现
int lucas(LL a, LL b)
{
if (a < mod && b < mod)
{
return C(a, b);
}
return (LL)C(a % mod, b % mod) * lucas(a / mod, b / mod) % mod;
}
int main()
{
// a和b的数值大,用longlong接收
LL a, b;
cin >> a >> b;
return 0;
}
组合计数(4)
#include <iostream>
#include <vector>
using namespace std;
// 利用高精度输出整个 C(a,b)
// 步骤: (1)将整个 C(a,b) 分解质因数,C(a,b) = a! / ((a - b)! * b!) ,所以 p在 C(a,b) 中的次数 = p在 a! 阶乘中的次数 - p在 (a - b)! 中的次数 - p在 b 阶乘中的次数
// (2)再用高精度将所有质因数乘进去
const int N = 5010;
int primes[N], cnt; // 筛选出质数放入
bool st[N];
int num[N]; // 记录每一个质数在分解质因数中的次数
// 筛选除质数,便于后面分解质因数
void get_primes(int n)
{
for (int i = 2; i <= n; i++)
{
if (!st[i])
{
primes[cnt++] = i;
}
for (int j = 0; primes[j] <= n / i; j++)
{
st[primes[j] * i] = true;
if (i % primes[j] == 0)
{
break;
}
}
}
}
// 求出 n!中 p 的次数
// 公式:get(n,p) = (n / p) + (n / p^2) + (n / p^3) + ……
int get(int n, int p)
{
int res = 0;
while (n)
{
res += n / p;
n /= p;
}
return res;
}
// 高精度乘法:C = A * b, A >= 0, b > 0
vector<int> mul(vector<int>& A, int b)
{
vector<int> C;
for (int i = 0, t = 0; i < A.size() || t; i++)
{
if (i < A.size())
{
t += A[i] * b; // 不同于一般乘法
}
C.push_back(t % 10);
t /= 10;
}
return C;
}
int main()
{
int a, b;
cin >> a >> b;
// 预处理出 1 - a中的质数,方便后面分解质因数
get_primes(a);
// 求出每个质数在 C(a,b) 中的次数
for (int i = 0; i < cnt; i++)
{
int p = primes[i];
num[i] = get(a, p) - get(b, p) - get(a - b, p);
}
// 将每个质因数乘入高精度中
vector<int> res;
res.push_back(1);
for (int i = 0; i < cnt; i++)
{
for (int j = 0; j < num[i]; j++)
{
res = mul(res, primes[i]);
}
}
// 输出结果,注意是从后往前输出
for (int i = res.size() - 1; i >= 0; i--)
{
cout << res[i];
}
return 0;
}