看了看网上关于 LucasLucasLucas 的讲解,感觉很多充斥着大量难懂的公式,对于小学生初学者来说不太友好,于是决定写一篇没有任何算法数学基础的人都能看懂的 LucasLucasLucas 。(当然本文中也会出现一些公式,不过没有 ∑\sum∑ 这种令人难受的符号而且公式大多特别简单)
LucasLucasLucas 定理主要用于大组合数取膜。
他的结论很简单:当且仅当 ppp 为质数时,Cmn mod p=Cm mod pn mod p×Cm÷pn÷p mod pC_m^n\, mod\,p = C_{m\,mod\,p}^{n\, mod\, p} \times C_{m\div p}^{n\div p}\,mod\,pCmnmodp=Cmmodpnmodp×Cm÷pn÷pmodp
由于作者太弱并不会证明,如果对恶心的证明感兴趣可以左转百度。
在 n,mn,mn,m 很大而 ppp 又很小的时候就可以使用 LucasLucasLucas 定理。
写个递归就可以实现 LucasLucasLucas 定理啦(本文所有代码均默认已经添加了typedef long long ll
)!
inline ll Lucas(ll m, ll n) {
return n == 0 ? 1 : C(m % p, n % p) * Lucas(m / p, n / p) % p;
}
慢着,你以为这就完了?
LucasLucasLucas 函数已经很优秀了,可是组合数如果按照杨辉三角计算…… LucasLucasLucas 复杂度+n。
按公式计算呢?炸了。
这里科普一个叫逆元的东西,它是拿来干啥的呢?
我们知道:
(a+b) mod p=(a mod p+b mod p) mod p(a+b)\,mod\,p=(a\,mod\,p+b\,mod\,p)\,mod\,p(a+b)modp=(amodp+bmodp)modp
(a+b) mod p=(a mod p−b mod p+p) mod p(a+b)\,mod\,p=(a\,mod\,p-b\,mod\,p + p)\,mod\,p(a+b)modp=(amodp−bmodp+p)modp
(a×b) mod p=(a mod p×b mod p) mod p(a\times b)\,mod\,p=(a\,mod\,p\times b\,mod\,p)\,mod\,p(a×b)modp=(amod