卢卡斯定理
对于解决组合数取模求解时,可以使用 卢卡斯(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
\]
-
因为要求出 \(\binom{n\bmod p}{m\bmod p}\) 的值,所以用到 Lucas 定理 的时候,要保证 \(p\) 的范围不能太大。
-
其中 \(\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;
}
剩余的
- 相对于其他知识来说,Lucas定理也存在 ExLucas定理,用于求解 \(p\) 不为素数的情况。
- 卢卡斯定理的证明。