卢卡斯定理
Lucas 定理
引入
Lucas 定理用于求解大组合数取模的问题,其中模数必须为素数。正常的组合数运算可以通过递推公式求解(详见 排列组合),但当问题规模很大,而模数是一个不大的质数的时候,就不能简单地通过递推求解来得到答案,需要用到 Lucas 定理。
定义
Lucas 定理内容如下:对于质数
观察上述表达式,可知
时间复杂度为
=== "C++"
```cpp
long long Lucas(long long n, long long m, long long p) {
if (m == 0) return 1;
return (C(n % p, m % p, p) * Lucas(n / p, m / p, p)) % p;
}
```
=== "Python"
```python
def Lucas(n, m, p):
if m == 0:
return 1
return (C(n % p, m % p, p) * Lucas(n // p, m // p, p)) % p
```
证明
考虑
注意过程中没有用到费马小定理,因此这一推导不仅适用于整数,亦适用于多项式。因此我们可以考虑二项式
考虑二项式
注意前者只有在
exLucas 定理
Lucas 定理中对于模数
过程
第一部分:中国剩余定理
要求计算二项式系数
考虑利用 中国剩余定理 合并答案,这种情况下我们只需求出
根据 唯一分解定理,将
对于任意
我们发现,在求出
第二部分:移除分子分母中的素数
根据同余的定义,
根据组合数定义
由于式子是在模
同余方程
然而 无法保证有解,发现无法直接求
所以将原式转化为:
第三部分:Wilson 定理的推论
问题转化成,求形如:
的值。这时可以利用 Wilson 定理的推论。如果难以理解,可以看看下面的解释。
解释
一个示例:22! mod 9
先考虑
比如
将其中所有
可以看到,式子分为三个整式的乘积:
-
是
的幂,次数是 ; -
是
,即 ,由于阶乘中仍然可能有 的倍数,考虑递归求解; -
是
中与 互质的部分的乘积,具有如下性质:
,
即: ( 是任意正整数)。
一共循环了 次,暴力求出 ,然后用快速幂求 次幂。
最后要乘上 ,即 ,显然长度小于 ,暴力乘上去。
上述三部分乘积为
所以有:
于是:
等式的右边两项不含素数 q。事实上,如果直接把 n 的阶乘中所有 q 的幂都拿出来,等式右边的阶乘也照做,这个等式可以直接写成:
式中的
递归的结果,三个部分中,左边部分随着递归结束而自然消失,中间部分可以利用 Wilson 定理的推论 0,右边部分就是推论 2 中的
下面这种写法,拥有单次询问 int inverse(int x)
函数返回
若不考虑 excrt 的复杂度,通过预处理
习题
贡献者:@Menci@Great-designer@WenzelTian@Sheng-Horizon@Ir1dXD@YOYO-UIAT@玉米@LuoYisu
本页面最近更新:2/3/2023, 12:00:00 AM,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用