组合数/Lucas定理

组合数公式:

通项:

$C(n,m) = n!/(m!*(n-m)!)$

递推:

$C(n,m) = C(n-1,m-1)+C(n-1,m)$

Lucas定理:

适用于p是质数,且p较小的情况

$Lucas(n,m) = Lucas(n/p,m/p) * C(n$ $mod$ $p,m$ $mod$ $p)$ $(mod$ $p)$

$Lucas(n,0) = 1$

代码如下

板子题

const int maxn = 1e5+10;
int t,n,m,p;
long long f[maxn];

void get_fac() {
    f[0] = 1;
    for(int i = 1; i <= p; i++)
        f[i] = (f[i-1]*i) % p;
}

int qpow(int a,int b){
    long long ans = 1,base = a;
    while(b){
        if(b&1) ans = (ans*base) % p;
        base = (base*base) % p;
        b >>= 1;
    }
    return ans;
}

int inv(int x){
    return qpow(x,p-2);
}

int C(int n,int m){
    if(m > n) return 0;
    return f[n] * inv(f[m])%p * inv(f[n-m])%p;
}

int lucas(int n,int m){
    if(m == 0) return 1;
    return (long long)lucas(n/p,m/p) * C(n%p,m%p) % p;
}

int main() {
    scanf("%d",&t);
    while(t--) {
        scanf("%d%d%d",&n,&m,&p);
        get_fac();
        printf("%d
",lucas(n+m,m));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/mogeko/p/11809572.html