Lucas定理--组合数取模

Lucas定理是用来求 c(n,m) mod p,p为素数的值。

C(n, m) % p = C(n / p, m / p) * C(n % p,m % p) % p 

\(Lucas(n,m,p)=C(n \% p,m \% p) \times Lucas(\frac{n}{p},\frac{m}{p},p)\)

\(\binom{n}{m}=\frac{n!}{m!(n-m)!}\)

卢卡斯定理模板

#include <cstdio>
#include <iostream>
#define ll long long
using namespace std;
ll pow(ll a,ll b,ll p){
    ll ans = 1; a %= p;
    while(b){
        if(b & 1)ans = ans * a % p;
        b >>= 1;
        a = a * a % p;
    }
    return ans;
}
ll inv(ll x, ll p){//x关于p的逆元,p为素数
    return pow(x, p - 2, p);
}
ll C(ll n, ll m, ll p){//求组合数C(n,m)%p
    if(n < m) return 0;
    ll up = 1, down = 1;//分子分母
    for(ll i = n - m + 1; i <= n; i++) up = up * i % p;
    for(ll i = 1; i <= m; i++) down = down * i % p;
    return up * inv(down, p) % p;
}
ll lucas(ll n, ll m, ll p){
    if(m == 0) return 1;
    return C(n % p, m % p, p) * lucas(n / p, m / p, p) % p;
}
int main(){
    ll n, m, p;
    scanf("%lld%lld%lld", &n, &m, &p);
    printf("%lld\n", lucas(n, m, p));
    return 0;
}
posted @ 2019-10-27 11:16  Emcikem  阅读(188)  评论(0编辑  收藏  举报