数学杂谈#2
一般的 Lucas 定理
相信你应该很熟练了
Lucas 定理
普通 Lucas 定理的形式如下:
对于正整数 \(n,m\) 和素数 \(p\) ,有:
为了方便,下面我们将 \(\lfloor\frac{n}{p}\rfloor\) 直接记作 \(n/p\) ,所以 Lucas 定理就是:
\[\binom n m \equiv \binom{n/p}{m/p}\binom{n\bmod p}{m\bmod p}\pmod p \]
简单证明:
利用如下等式:
二项式定理:
\[\begin{aligned} (1+x)^p &\equiv \sum_{i=0}^p\binom{p}{i}x^i\pmod p\\ \end{aligned} \]注意到当 \(1\le k<p\) 的时候, \(\binom{p}{k}\) 都必然含有 \(p\) 因子,所以:
\[(1+x)^p\equiv 1+x^p\pmod p \]
另一个更快的方式是使用费马小定理。设 \(y=1+x\) ,则:
\[y^p\equiv y\equiv 1+x\equiv 1+x^p\pmod p \]
设 \(n=kp+r(0\le r<p)\) 。
那么就有:
两边同时取 \([x^m](0\le m\le n)\) 。设 \(m=sp+t(0\le t<p)\) ,当 \(t\le r\) 的时候,有:
注意,当 \(t>r\) 的时候,必然有 \(\binom{n}{m}\bmod p= 0\) ,而此时 \(\binom{r}{t}\bmod p=0\) ,所以可以写作这个形式。
为什么当 \(t>r\) 时,有 \(\binom{n}{m}=0\) ?
这就意味着, \(\binom{n}{m}\) 包含 \(p\) 因子。
利用勒让德定理,其中 \(p\) 的次数为:
\[\sum_{k=1}n/p^k-m/p^k-(n-m)/p^k \]显然每一位都 \(\ge 0\) 。
结合 \(t>r\) ,所以 \(m+(n-m)\) 在 \(p\) 进制下的 \(p^0\) 这一位必然是进了位的,所以有:
\[n/p-m/p-(n-m)/p>0 \]因此 \(\binom{n}{m}\) 必包含 \(p\) 。
Lucas 定理的运用
Lucas 定理一般拿来计算组合数取模的值。
这难道不是它的本职工作吗
当 \(p\) 比较小的时候,我们可以预处理一下 \(n,m<p\) 时候的组合数,然后就可以递归算。
时间是 \(O(p)-O(\log_p n)\) 。
当 \(p\) 不是素数的时候,需要使用 exLucas 计算。
关于 Lucas 定理的扩展内容
仔细观察 Lucas 定理。设 \(n=(n_1n_2\ldots n_k)_p,m=(m_1m_2\ldots m_k)_p\) ,那么有:
因此, Lucas 定理相当于是在 \(p\) 进制下,对每一位单独算组合数,最后合起来。
这也告诉我们,在 \(p\) 进制中,每一位的组合数是独立的,我们就可以进行数位 DP 等等。
例题:[清华集训2016] 组合数问题 。
计算进位次数。
这真的有关系吗?
这里需要祭出一个 Kummer 定理:
对于正整数 \(n,p\) ,设 \(\bold v_p(n)\) 为 \(n\) 所包含的 \(p\) 的幂次。
对于正整数 \(n,m\) 和素数 \(p\) , \(\bold v_p(\binom{n}{m})\) 即为 \(m+(n-m)\) 在 \(p\) 进制下的进位次数。
看起来就像在扯淡
简单证明:
计算一下 \(\bold v_p(\binom n m)\) :
另外,对于正整数 \(n,m,p\) ,都有恒等式成立:
所以有:
所以就是枚举判断 \(p\) 进制下的第 \(k\) 位是否进位。
关于恒等式的证明:
设 \(n=v_1p+k_1,m=v_2p+k_2,(n-m)=v_3p+k_3(0\le k_1,k_2,k_3<p)\) 。
现在考虑 \(n/p-m/p-(n-m)/p=v_1-v_2-v_3\) ,如果有进位,则 \(v_1-v_2-v_3=1\) ,否则有 \(v_1-v_2-v_3=0\) 。
另一方面,如果有进位,那么余数应该加和大于 \(p\) ,所以如果 \(k_2+k_3\ge p\) ,则有进位,否则没有进位。
一般这个性质可以用在数位 DP 里面。
啊这,跟 Lucas 定理有什么关系吗?
一个比较有意思的转化。
根据 Lucas 定理,我们知道:
但是,对于形式变元 \(x^n\) ,也有:
这个形式和 Lucas 定理很像不是吗?考虑将两者结合起来看:
当然,如果将 \(x^n\) 换做 \(x^m\) ,效果也是几乎一样的。
在一个实际的例子中,我们可以计算:
根据上面的式子推导一下:
计算这个式子的时候,由于 \(n\) 固定,所以 \(n\bmod p\) 只有 \(O(\log_p n)\) 种有效取值,对于每种取值都可以预处理出 \(\binom{n\bmod p}{k}x^k\) 的前缀和,所以可以 \(O(p\log_p n)\) 预处理,再 \(O(\log_p m)\) 计算一次答案。
exLucas
一般认为 exLucas 是一个算法,跟 Lucas 作为定理的本质不同。
exLucas 求解的也是组合数取模的问题。
也就是,对于正整数 \(n,m\) 和任意较小正整数 \(P\) ,我们都可以较快地计算 \(\binom{n}{m}\bmod P\) 的结果。
第一步
我们需要将 \(P\) 进行分解,拆分成 \(\prod_{i=1}^kp_i^{e_i}\) 。根据 CRT 我们知道 \(\binom{n}{m}\) 对于每个 \(p_i^{e_i}\) 取模的结果最终必然可以唯一确定一个 \(\bmod P\) 意义下的值。
第二步
考虑计算 \(\binom{n}{m}\bmod p^e\) ,其中 \(p\) 是素数,且 \(e\) 是正整数。
将组合数展开成阶乘:
后一步提出 \(p\) 因子变化是很有必要的,不然我们极有可能会在直接 \(n!\) 计算的过程中算出三个 0 ,然后只能发呆......
其中 \(\bold v_p(n!)\) 三个部分可以使用 Legendre 定理计算。
第三步
设 \(f(n)=\frac{n!}{p^{\bold v_p(n!)}}\bmod p^e\) ,我们现在只需要能快速计算 \(f\) 的值即可。
考虑参考 Lucas 定理的证明过程,将 \(n!\) 的因子分类:
注意到最终结果的第一个 \(\prod\) 内的值是不随 \(n\) 变化的,因此可以直接统计它的幂次之和,最后一次计算;而 \((n/p^e\times p^e,n]\) 的尾巴部分,在 \(\bmod p^e\) 意义下等价于 \((0,n\bmod p^e]\) ,因此可以预处理一组互质前缀积。
计算时间是 \(O(p^e)-O(\log_pn)\) 。
可以发现 exLucas 最有用的部分其实就是 第三步 内提到的阶乘算法。因此 exLucas 也可用于计算 \(p^e\) 较小时候的阶乘。
再大?再大就得写多项式了