lucas定理
正题
首先,这玩意就是下面这个式子:
C
m
n
%
p
=
C
m
/
p
n
/
p
∗
C
m
%
p
n
%
p
%
p
C_m^n\%p=C_{m/p}^{n/p}*C_{m\%p}^{n\%p}\%p
Cmn%p=Cm/pn/p∗Cm%pn%p%p
当且仅当
p
p
p为质数。
当然,还有一个形式:
首先把n写成一个p进制下的东东:
n
=
∑
a
i
∗
p
i
n=\sum a_i*p^i
n=∑ai∗pi
在把m写成一个p进制下的东东:
m
=
∑
b
j
∗
p
j
m=\sum b_j*p^j
m=∑bj∗pj
然后
C
m
n
=
Π
C
b
i
a
i
%
p
C_m^n=\Pi C_{b_i}^{a_i}\%p
Cmn=ΠCbiai%p
证明,由于则不是主要内容,所以在此不展开了。自己上百度。
或者这里有一张图:(转的)
其实是太懒了
拓展lucas定理
前言
这个东东是解决
C
m
n
%
p
C_m^n\%p
Cmn%p其中p不为质数的情况的。
其实和上面的lucas做法没有半点关系。
前置姿势
中国剩余定理、拓展gcd
没了。
中国剩余定理:(百度百科)
exgcd:(百度百科)
正文
直接求解
C
m
n
%
P
C_m^n\%P
Cmn%P我们需要两个条件,一个是能够快速求出
n
!
n!
n!,一个是能快速求出逆元。
然而当n和m都奇大无比时, 且p不为质数。那么就很头痛了。
然后拓展lucas定理(其实都可以不必叫定理了)就可以比较好地解决这个问题。
而这也不是万能的,lucas定理可以运用的前提是p这个合数分解质因数不能是一个巨大的质数乘上一个巨小的质数。
当然,这个可以当做一个判断是否用拓展lucas的一个条件。
讲这么多废话,那么现在开始。
首先,我们要求的东东长这样:
C
m
n
%
P
=
m
!
n
!
(
m
−
n
)
!
%
P
C_m^n\%P=\frac{m!}{n!(m-n)!}\%P
Cmn%P=n!(m−n)!m!%P
首先,我们考虑用拓展中国剩余定理来简化一下这个东东:
{
x
≡
C
m
n
(
%
p
1
q
1
)
x
≡
C
m
n
(
%
p
2
q
2
)
x
≡
C
m
n
(
%
p
3
q
3
)
…
…
\left\{\begin{matrix}x\equiv C_m^n(\%p_1^{q_1})\\ x\equiv C_m^n(\%p_2^{q_2})\\ x\equiv C_m^n(\%p_3^{q_3})\\ …… \end{matrix}\right.
⎩⎪⎪⎨⎪⎪⎧x≡Cmn(%p1q1)x≡Cmn(%p2q2)x≡Cmn(%p3q3)……
如果我们求出右式,那么意味着我们可以用中国剩余定理直接合并。
那么问题则转化为求解:
C
m
n
%
p
q
C_m^n\%p^q
Cmn%pq
那么我们现在的问题就有两个,一个是如何快速求出阶乘。其次是如何求出这个阶乘的逆元。
求逆元
就以求
n
!
n!
n!为例
由于
n
!
n!
n!中有许许多多的因子为
p
p
p的数。
那么这就不与模数互质了,于是就不能直接套exgcd来求逆元。
怎么办?
考虑从
n
!
n!
n!把这些
p
p
p的因子给提出来。
我们原式就变为:
n
!
p
x
∗
p
x
\frac{n!}{p^x}*p^x
pxn!∗px。其中
x
x
x是一个未知量,且我们这个x要尽量大使得
n
!
p
x
\frac{n!}{p^x}
pxn!里没有
p
p
p的因子。
我们可以知道,一共有
⌊
n
p
⌋
\lfloor\frac{n}{p}\rfloor
⌊pn⌋个这些p的因子,然后他们组成情况为:
Π
i
=
1
⌊
n
p
⌋
i
∗
p
\Pi_{i=1}^{\lfloor\frac{n}{p}\rfloor}i*p
Πi=1⌊pn⌋i∗p
化简得:
(
⌊
n
p
⌋
)
!
∗
p
⌊
n
p
⌋
(\lfloor\frac{n}{p}\rfloor)!*p^{\lfloor\frac{n}{p}\rfloor}
(⌊pn⌋)!∗p⌊pn⌋
那么
n
!
n!
n!就被我们化成:
(
⌊
n
p
⌋
)
!
∗
p
⌊
n
p
⌋
∗
Π
i
=
1
n
[
i
≢
0
%
p
q
]
i
(\lfloor\frac{n}{p}\rfloor)!*p^{\lfloor\frac{n}{p}\rfloor}*\Pi_{i=1}^n[i\not \equiv 0\%p^q]i
(⌊pn⌋)!∗p⌊pn⌋∗Πi=1n[i≡0%pq]i
然鹅
(
⌊
n
p
⌋
)
!
(\lfloor\frac{n}{p}\rfloor)!
(⌊pn⌋)!还是有可能有
p
p
p的因子,因此我们考虑设个
f
(
n
)
=
n
!
p
x
f(n)=\frac{n!}{p^x}
f(n)=pxn!
于是原式可以通过递归的方法求解。其中我们的
p
⌊
n
p
⌋
p^{\lfloor\frac{n}{p}\rfloor}
p⌊pn⌋可以在外面被
p
x
p^x
px给化简掉,所以递归过程忽略。
那么递推式变为:
f ( n ) = f ( ⌊ n p ⌋ ) ∗ Π i = 1 n [ i ≢ 0 % p q ] i f(n)=f(\lfloor\frac{n}{p}\rfloor)*\Pi_{i=1}^n[i\not \equiv 0\%p^q]i f(n)=f(⌊pn⌋)∗Πi=1n[i≡0%pq]i
这样我们就可以求出
n
!
p
x
\frac{n!}{p^x}
pxn!
然后外面的
p
x
p^x
px我们一样考虑通过递归来求出x的值。
设
g
(
n
)
=
x
g(n)=x
g(n)=x
那么递归过程中,每次消去
⌊
n
p
⌋
\lfloor\frac{n}{p}\rfloor
⌊pn⌋,且阶乘一样产生贡献。
因此递归式为:
g
(
n
)
=
⌊
n
p
⌋
+
g
(
⌊
n
p
⌋
)
g(n)=\lfloor\frac{n}{p}\rfloor+g(\lfloor\frac{n}{p}\rfloor)
g(n)=⌊pn⌋+g(⌊pn⌋)
至此,我们已经解决了求逆元的问题。
求阶乘
我们发现,上面的递推式中:
Π
i
=
1
n
[
i
≢
0
%
p
q
]
i
\Pi_{i=1}^n[i\not \equiv 0\%p^q]i
Πi=1n[i≡0%pq]i长得不是很好看。
但是我们发现,由于是在模
p
q
p^q
pq意义下的东西,所以这玩意是有周期的。
怎么理解?
比如:
1
、
2
、
4
、
5
、
7
、
8
、
10
、
11
、
13
、
14
、
16
、
17
1、2、4、5、7、8、10、11、13、14、16、17
1、2、4、5、7、8、10、11、13、14、16、17其中
p
=
3
,
q
=
2
p=3,q=2
p=3,q=2
(去除了有因子3的数)
我们发现,
1
∗
2
∗
4
∗
5
∗
7
∗
8
1*2*4*5*7*8
1∗2∗4∗5∗7∗8和
10
∗
11
∗
13
∗
14
∗
16
∗
17
10*11*13*14*16*17
10∗11∗13∗14∗16∗17在模意义下是相同的。
那么我们就可以只算出一个周期的值,然后再把这些周期值快速幂乘起来。
然后可能剩下一小段,那么由于比较小,所以直接暴力乘起来即可。
Π i = 1 n [ i ≢ 0 % p q ] i = ( Π i = 1 p q [ i ≢ 0 % p q ] i ) ⌊ n p ⌋ ∗ ( Π i = p q ∗ ⌊ n p ⌋ n [ i ≢ 0 % p q ] i ) \Pi_{i=1}^n[i\not \equiv 0\%p^q]i=(\Pi_{i=1}^{p^q}[i\not \equiv 0\%p^q]i)^{\lfloor\frac{n}{p}\rfloor}*(\Pi_{i=p^q*\lfloor\frac{n}{p}\rfloor}^{n}[i\not \equiv 0\%p^q]i) Πi=1n[i≡0%pq]i=(Πi=1pq[i≡0%pq]i)⌊pn⌋∗(Πi=pq∗⌊pn⌋n[i≡0%pq]i)
代码
(看例题)
例题
luoguP4720 【模板】扩展卢卡斯
jzoj3214. 【SDOI2013】方程
参考资料
https://blog.csdn.net/qq_30115697/article/details/88942177
https://www.luogu.com.cn/problem/P4720 中的fading题解
各种百度百科