夜深人静写算法(三十九)- 卢卡斯定理
Posted 英雄哪里出来
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了夜深人静写算法(三十九)- 卢卡斯定理相关的知识,希望对你有一定的参考价值。
一、前言
有人问我,你这些东西应该是你当时做 ACM 竞赛时候的东西了,现在都毕业十年了,为什么还在搞这些啊?公众号很赚钱吗?
我想说的是,《夜深人静写算法》这个公众号(暂时)不是为了赚钱。要不是因为情怀,我可能早就弃坑公众号了。
有时候,既然开始了,就一直做下去吧,不然当时为什么要开始呢?就像既然谈恋爱了,就一直爱下去吧,毕竟曾经爱过。既然无法逃离沉没成本的枷锁,就当记录自己逝去的青春吧。
这周要更新的内容,还是目前工作中对我来说,毫无用处的东西,纯粹是为了刷题爽,一直刷题一直爽的 卢卡斯定理。
二、问题引入
【例题1】给定 n , m , p ( 0 ≤ n ≤ 1 0 9 , 0 ≤ m ≤ n , 1 ≤ p ≤ 1 0 5 ) n, m, p (0 \\le n \\le 10^9, 0 \\le m \\le n, 1 \\le p \\le 10^5) n,m,p(0≤n≤109,0≤m≤n,1≤p≤105),其中 p p p 为素数,求 C n m m o d p C_n^m \\ mod \\ p Cnm mod p。
- 其中 C n m C_n^m Cnm 是组合数,即 n n n 个不同的物品选择 m m m 个的方案数。
1、递推公式
-
组合数满足递推公式如下:
-
C n m = { 1 m = 0 1 m = n C n − 1 m − 1 + C n − 1 m 1 ≤ m < n C_n^m = \\begin{cases}1 & m = 0 \\\\ 1 & m = n\\\\ C_{n-1}^{m-1} + C_{n-1}^{m} & 1 \\le m \\lt n\\end{cases} Cnm=⎩⎪⎨⎪⎧11Cn−1m−1+Cn−1mm=0m=n1≤m<n
-
由于 n n n 的值非常大,利用上述递推的时间复杂度为 O ( n m ) O(nm) O(nm),所以无法满足该题的需求。
2、通项公式
- 组合数满足通项公式如下:
- C n m = n ! m ! ( n − m ) ! C_n^m = \\frac {n!}{m!(n-m)!} Cnm=m!(n−m)!n!
- 由于要求的是 模 p p p,所以可以引入逆元的概念,即:
- C n m m o d p = n ! m ! ( n − m ) ! m o d p = n ! ( m ! ) − 1 ( ( n − m ) ! ) − 1 m o d p \\begin{aligned}C_n^m \\ mod \\ p &= \\frac {n!}{m!(n-m)!} \\ mod \\ p \\\\ &= n!(m!)^{-1}((n-m)!)^{-1} \\ mod \\ p\\end{aligned} Cnm mod p=m!(n−m)!n! mod p=n!(m!)−1((n−m)!)−1 mod p
- 可以通过 O ( n ) O(n) O(n) 的时间复杂度计算 n ! m o d p n! \\ mod \\ p n! mod p 和 ( n ! ) − 1 m o d p (n!)^{-1} \\ mod \\ p (n!)−1 mod p,然后还是因为 n n n 太大, 这个方法还是无法满足要求。
三、卢卡斯定理
1、定义
- 卢卡斯定理如下:
- C n m ≡ C n / p m / p C n m o d p m m o d p ( m o d p ) C_n^m \\equiv C_{n/p}^{m/p} C_{n\\ mod \\ p}^{m\\ mod \\ p} (mod \\ p) Cnm≡Cn/pm/pCn mod pm mod p(mod p)
- 其中 p p p 为素数。
2、证明
- 在证明卢卡斯定理的时候,需要用到一些引理,接下里首先对引理进行证明。
1)引理1
【引理1】对于组合数 C p i C_p^i Cpi,其中 p p p 为素数,满足如下同余式成立: C p i ≡ 0 ( m o d p ) ( 0 < i < p ) C_p^i \\equiv 0 \\ (mod \\ p) \\ \\ \\ \\ (0 \\lt i \\lt p) Cpi≡0 (mod p) (0<i<p)
- 这个引理的证明需要从组合数的定义公式出发,如下:
- C p i = p ! i ! ( p − i ) ! C_p^i = \\frac {p!}{i! (p-i)!} Cpi=i!(p−i)!p!
- 由于 0 < i < p 0 \\lt i \\lt p 0<i<p,且 p p p 为素数,所以 i ! i! i! 和 ( p − i ) ! (p-i)! (p−i)! 都不可能是 p p p 的因子。又因为组合数一定是一个整数,所以 i ! ( p − i ) ! i!(p-i)! i!(p−i)! 一定是 ( p − 1 ) ! (p-1)! (p−1)! 的因子,这样组合数就可以表示成:
- C p i = ( p − 1 ) ! i ! ( p − i ) ! p = k p C_p^i = \\frac {(p-1)!}{i! (p-i)!}p = kp Cpi=i!(p−i)!(p−1)!p=kp
- 等式两边同时模上
p
p
p,得到:
C p i ≡ 0 ( m o d p ) ( 0 < i < p ) C_p^i \\equiv 0 \\ (mod \\ p) \\ \\ \\ \\ (0 \\lt i \\lt p) Cpi≡以上是关于夜深人静写算法(三十九)- 卢卡斯定理的主要内容,如果未能解决你的问题,请参考以下文章