卢卡斯定理

对于解决组合数取模求解时,可以使用 卢卡斯(Lucas)定理 的内容解决。

当数据范围不大时,我们可以使用 1. 递推公式;2. 预处理阶乘 \(\dots\)许多方法进行。

但当 \(n,m\le 10^9\)\(p\le 1000\)\(p\) 为素数的时候,以上的方法都会用不了了。

Lucas 定理

内容

卢卡斯定理的内容为:对于任意 \(p\) 为素数,有

\[\binom{n}{m}\bmod p= \binom{\left\lfloor \tfrac{n}{p}\right\rfloor}{\left\lfloor \tfrac{m}{p}\right\rfloor}\cdot\binom{n\bmod p}{m\bmod p}\bmod p \]

  1. 因为要求出 \(\binom{n\bmod p}{m\bmod p}\) 的值,所以用到 Lucas 定理 的时候,要保证 \(p\) 的范围不能太大。

  2. 其中 \(\binom{\left\lfloor n/p\right\rfloor}{\left\lfloor m/p\right\rfloor}\bmod p\) 可以使用 Lucas定理 继续求解,直到边界条件 \(m = 0\) 返回 \(1\)

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

特别地

卢卡斯定理,也可以理解为:

\(n\)\(m\) 转换为两个 \(p\) 进制数,然后对 这两个 \(p\) 进制数的相同的位的数,进行组合数取模,然后相乘。

\[\binom{n}{m}\bmod p= \prod_{i=1}^{k}\binom{n_{(p)_i}}{m_{(p)_i}}\bmod p \]

int lucas(int n,int m)
{
    x[0]=y[0]=0;
    int ans=1;
    while(n){x[++x[0]]=n%p; n/=p;}
    while(m){y[++y[0]]=m%p; m/=p;}
    for(int i=1;i<=max(x[0],y[0]);i++){
        ans=ans*C[x[i]][y[i]]%p;
    }
    return ans;
}

剩余的

  1. 相对于其他知识来说,Lucas定理也存在 ExLucas定理,用于求解 \(p\) 不为素数的情况。
  2. 卢卡斯定理的证明。
posted @ 2023-01-13 08:46  Ciaxin  阅读(120)  评论(0编辑  收藏  举报