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