费马定理以及逆元预处理
const int MOD = 1000000007; // 模数,通常是大素数
const int MAXN = 100000; // 设定最大值
long long fact[MAXN + 1]; // 阶乘数组
long long inv_fact[MAXN + 1]; // 逆阶乘数组
// 快速幂算法:计算 (base^exp) % MOD
long long power(long long base, long long exp) {
long long result = 1;
while (exp > 0) {
if (exp % 2 == 1) result = (result * base) % MOD; // 如果指数是奇数,乘上当前base
base = (base * base) % MOD; // 将base自乘,用于计算指数的更高次幂
exp /= 2; // 指数右移,等效于 exp //= 2
}
return result;
}
// 预处理阶乘和逆阶乘
void precompute(int n) {
fact[0] = 1;
for (int i = 1; i <= n; ++i) {
fact[i] = fact[i - 1] * i % MOD; // 计算阶乘: fact[i] = i!
}
// 计算逆阶乘:利用费马小定理计算 fact[n] 的逆元
inv_fact[n] = power(fact[n], MOD - 2); // 计算 fact[n] 的逆元,等价于 fact[n]^(MOD-2) % MOD
for (int i = n - 1; i >= 0; --i) {
inv_fact[i] = inv_fact[i + 1] * (i + 1) % MOD; // 根据 fact[i] 和 fact[i+1] 计算出 inv_fact[i]
}
}
// 计算组合数 C(n, r) = n! / (r! * (n - r)!)
long long combination(int n, int r) {
if (r < 0 || r > n) return 0; // 如果 r 小于 0 或者大于 n,返回 0
return fact[n] * inv_fact[r] % MOD * inv_fact[n - r] % MOD; // 计算组合数
}
动态规划求组合数(mod可省去)
vector<vector<int>> dp(n + 1, vector<int>(k + 1, 0));
for (int i = 0; i <= n; i++) {
dp[i][0] = 1; // C(i, 0) = 1
for (int j = 1; j <= min(i, k); j++) {
dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j]) % mod; // 递推关系
}
}

浙公网安备 33010602011771号