费马定理以及逆元预处理

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;  // 递推关系
    }
}
posted @ 2025-01-19 13:49  Qacter  阅读(64)  评论(0)    收藏  举报