洛谷 #3807. 【模板】卢卡斯定理

版权声明:转载请注明出处 https://blog.csdn.net/qq_41593522/article/details/84402965

题意

求C(n + m, m) % p,保证p为质数

题解

卢卡斯定理

对C(m, n),令

\(m = k_1 * p + r_1\)

\(n = k_2 * p + r_2\)

则 \(C(m, n) = C(k_1, k_2) * C(r_1, r_2)\)

调试记录

#include <cstdio>
#define maxn 200005
#define int long long

using namespace std;

int T, n, m, mo, fac[maxn], inv[maxn];

int C(int m, int n){
    if (m < n) return 0;
    if (n == 0 || n == m) return 1;
    
    return fac[m] * inv[n] % mo * inv[m - n] % mo;
}

int Lucas(int m, int n){
    if (m < n) return 0;
    if (n == 0 || n == m) return 1;
    if (n < mo && m < mo) return C(m, n);
    
    return Lucas(m / mo, n / mo) * Lucas(m % mo, n % mo) % mo;
}

signed main(){
    scanf("%lld", &T);
    
    while (T--){
        scanf("%lld%lld%lld", &n, &m, &mo);
        fac[1] = 1; inv[1] = 1;
        for (int i = 2; i <= n + m; i++) fac[i] = fac[i - 1] * i % mo;
        for (int i = 2; i <= n + m; i++) inv[i] = (mo - mo / i) * inv[mo % i] % mo;
        for (int i = 2; i <= n + m; i++) inv[i] = inv[i] * inv[i - 1] % mo;
        printf("%lld\n", Lucas(n + m, m));
    }
    
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41593522/article/details/84402965