卢卡斯定理及其卢卡斯定理的拓展

  • 前言:

求一个组合数 C_{n}^{m} (mod\,\, p),我们可以通过逆元的方式在 O(n)的时间复杂度内求出

但如果数特别大时(数据范围 n \leqslant 1e18\,\,\,\,\,\,\,\, m \leqslant 1e18 \,\,\,\,\, p \leqslant 1e5),又该怎么办

使用卢卡斯定理求解

 

  • 卢卡斯定理:(组合数取模,取模的模数只能是质数)

C_{n}^{m} \equiv \prod _{i=0}^k C_{n_i}^{m_i} (mod\,\, p)

即  \begin{matrix}Lucas(n, m, p) = C_{m\,\,mod\,\,p}^{\,\,n\,\,mod\,\,p} \,\, * \,\, Lucas(n/p, m/p, p) \\ \,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,= \frac{\ n!}{\ m! * \ (n-m)!} * Lucas(n/p, m/p, p) \end{matrix}

模板:

#include<bits/stdc++.h>
typedef long long LL;

using namespace std;

const int N = 100000 + 5;
LL mul(LL a, LL b, LL p){//快速乘,计算a*b%p
    LL ret = 0;
    while(b){
        if(b & 1) ret = (ret + a) % p;
        a = (a + a) % p;
        b >>= 1;
    }
    return ret;
}
LL fact(int n, LL p){//n的阶乘求余p
    LL ret = 1;
     for (int i = 1; i <= n ; i ++) ret = ret * i % p ;
    return ret ;
}
void ex_gcd(LL a, LL b, LL &x, LL &y, LL &d){
    if (!b) {d = a, x = 1, y = 0;}
    else{
        ex_gcd(b, a % b, y, x, d);
        y -= x * (a / b);
    }
}
LL inv(LL t, LL p){//如果不存在,返回-1
    LL d, x, y;
    ex_gcd(t, p, x, y, d);
    return d == 1 ? (x % p + p) % p : -1;
}
LL comb(int n, int m, LL p){//C(n, m) % p
    if (m < 0 || m > n) return 0;
    return fact(n, p) * inv(fact(m, p), p) % p * inv(fact(n-m, p), p) % p;
}
LL Lucas(LL n, LL m, int p){
        return m ? Lucas(n/p, m/p, p) * comb(n%p, m%p, p) % p : 1;
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--){
        LL n, m, p;
        scanf("%lld%lld%lld", &n, &m, &p);
        printf("%lld\n", Lucas(n, m, p));   //求C(n, m) % p
    }
    return 0;
}

 

  • 扩展卢卡斯定理(可以处理模数为非质数的情况)

对于这样一个组合数:

C_{n}^{m} \,\, \% \,\, p (p不是质数)

例如:举这样一个例子,C_{10}^{3} \,\, \% \,\, p

          if p = 6时,120 % 6 = 0,

                            6 = 2 * 3  (算术基本定理) 时,120 % 2 = 0,120 % 3 = 0,取一个同时满足条件的正整数为0,即                                 C_{10}^{3} \,\, \% \,\, 6 = 0

          if p = 8时,120 % 98 = 22,

                            98=2*7^2(算术基本定理)时,120 % 2 = 0,120 % 49 = 22,取一个同时满足条件的正整数为22,                    即 C_{10}^{3}\,\, \% \,\, 98 = 22

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值