阶乘取模
引入
本文讨论了某一模数下阶乘计算的相关结论,并提供一种时间复杂度线性相关于模数大小的计算方法,因而该方法主要适用于模数不太大(∼106
)的情形。除了本文介绍的方法外,根据场景不同,还可以应用 多项式技术 进行快速计算。
根据 中国剩余定理,阶乘取模问题可以转化为模数为素数幂 𝑝𝛼
的情形。在处理这类问题时,常常需要对于素数 𝑝
和正整数 𝑛
,将阶乘 𝑛!
中的所有因子 𝑝
都提取出来,进而得到分解:
𝑛!=𝑝𝜈𝑝(𝑛!)(𝑛!)𝑝.
其中,𝜈𝑝(𝑛!)
表示阶乘 𝑛!
的素因数分解中 𝑝
的幂次,(𝑛!)𝑝
表示在阶乘 𝑛!
的结果中去除所有 𝑝
的幂次得到的整数。本文将讨论 (𝑛!)𝑝
在素数(幂)模下的余数以及幂次 𝜈𝑝(𝑛!)
的具体计算方法。
这种分解在解决阶乘同时出现在所求表达式的分子和分母的问题时尤为有用,比如 计算某一模数下的二项式系数。对于这类问题,分子和分母中 𝑝
的幂次可以直接相减,而与 𝑝
互素的部分 (𝑛!)𝑝
则可以利用 乘法逆元 计算。
本文还介绍了与上述问题相关的 Wilson 定理及其推广、Legendre 公式和 Kummer 定理等内容。
Wilson 定理
Wilson 定理给出了判断某个自然数是素数的一个充分必要条件。
Wilson 定理
对于自然数 𝑛 >1
,当且仅当 𝑛
是素数时,(𝑛 −1)! ≡ −1(mod𝑛)
。
证明
首先,证明对于素数 𝑝
有 (𝑝 −1)! ≡ −1(mod𝑝)
。对于这一点,可以利用 同余方程 或 原根 得到两种简洁的证明,此处略去不表。下面提供前置知识较少的一种证明方法:
当 𝑝 =2
时,命题显然成立。下面设 𝑝 ≥3
,继而要证明 𝐙𝑝
中所有非零元素(即同余类)的积为 ―――−1
。因为 𝐙𝑝
中所有非零元素 ――𝑎
都有逆元 ――𝑎−1
,于是 𝐙𝑝
中彼此互逆的元素乘积为 ――1
。但是要注意 ――𝑎
和 ――𝑎−1
可能相等:――𝑎 =――𝑎−1
,当且仅当 𝑎2 ≡1(mod𝑝)
,即
0≡𝑎2−1≡(𝑎+1)(𝑎−1),(mod𝑝)
从而,𝑎 ≡1(mod𝑝)
或 𝑎 ≡ −1(mod𝑝)
。这说明 𝐙𝑝 ∖{――0,――1,―――−1}
中所有元素的乘积为 ――1
,进而 𝐙𝑝
中所有非零元素的积为 ―――−1
。
反过来,对于合数 𝑛
的情形,要证明 (𝑛 −1)! ≢ −1(mod𝑛)
。利用反证法,不妨设 (𝑛 −1)! ≡ −1(mod𝑛)
,亦即存在整数 𝑘
使得 (𝑛 −1)! =𝑘𝑛 −1
成立。因为 𝑛
是合数,必然存在素数 𝑝 <𝑛
使得 𝑛 =𝑝𝑚
,所以 (𝑛 −1)! =𝑘𝑝𝑚 −1 ≡ −1(mod𝑝)
。但是,乘积 (𝑛 −1)!
中必然已经出现 𝑝
,故而一定有 (𝑛 −1)! ≡0(mod𝑝)
。这一矛盾就说明了 (𝑛 −1)! ≢ −1(mod𝑛)
。
利用本文的记号,Wilson 定理可以写作 (𝑝!)𝑝 ≡ −1(mod𝑝)
。
推广
Wilson 定理可以推广到一般模数的情形。
定理(Gauss)
对于自然数 𝑚 >1
,有
∏1≤𝑘<𝑚, 𝑘⟂𝑚𝑘≡±1(mod𝑚).
而且,余数中的 ±1
取值为 −1
当且仅当模 𝑚
的 原根存在,即 𝑚 =2,4,𝑝𝛼,2𝑝𝛼
时,其中 𝑝
是奇素数且 𝛼
是正整数。
证明
这个定理可以通过 模 𝑛
整数乘法群 的结构简单地证明。此处给出思路相仿,但是较为初等的证明。
对于 𝑚 =2
的情形,有 1! =1 ≡ −1(mod2)
。对于其他存在原根的情形,设原根为 𝑔
,则所有满足小于 𝑚
且与它互素的正整数 𝑘
都可以唯一地表示为 𝑔𝑖mod𝑚
的形式,其中 0 ≤𝑖 <𝜑(𝑚)
且 𝜑(𝑚)
是 Euler 函数。直接验证可知,𝜑(𝑚)
一定是偶数。因为 𝑔𝑖
和 𝑔𝜑(𝑚)−𝑖
互为乘法逆元,所以在乘积中将它们两两配对,就有
∏1≤𝑘<𝑚, 𝑘⟂𝑚𝑘≡𝜑(𝑚)−1∏𝑖=0𝑔𝑖=𝑔𝜑(𝑚)/2𝜑(𝑚)/2−1∏𝑖=1𝑔𝑖𝑔𝜑(𝑚)−𝑖≡𝑔𝜑(𝑚)/2(mod𝑚).
因为 𝑔𝜑(𝑚)/2mod𝑚
是唯一的不等于 1mod𝑚
且乘法逆元就是它自身的元素,所以它就等于 −1mod𝑚
。这就说明了此时的余数等于 −1
。
对于模 𝑚
的原根不存在的情形,要证明余数等于 1
。为此,可以首先做质因数分解 𝑚 =𝑝𝑒11𝑝𝑒22⋯𝑝𝑒𝑠𝑠
,然后应用 中国剩余定理 可知,只需要证明
∏1≤𝑘<𝑚, 𝑘⟂𝑚𝑘≡1(mod𝑝𝑒𝑗𝑗)
对所有因子 𝑝𝑒𝑗𝑗
都成立。中国剩余定理说明,每一个可能的余数组合 (𝑟1,𝑟2,⋯,𝑟𝑠)
,其中,1 ≤𝑟𝑗 <𝑝𝑒𝑗𝑗
且 𝑝𝑗⟂𝑟𝑗
,都唯一地对应着一个 1 ≤𝑘 <𝑚
且 𝑘⟂𝑚
使得 𝑘 ≡𝑟𝑗(mod𝑝𝑒𝑗𝑗)
成立。所以,对于某个余数 𝑟𝑗
,都恰好有 𝜑(𝑚)/𝜑(𝑝𝑒𝑗𝑗)
个 𝑘
使得 𝑘 ≡𝑟𝑗(mod𝑝𝑒𝑗𝑗)
成立。利用这一点,可以对乘积进行分组,就有
∏1≤𝑘<𝑚, 𝑘⟂𝑚𝑘≡⎛⎜
⎜
⎜
⎜⎝∏1≤𝑟𝑗<𝑝𝑒𝑗𝑗, 𝑟𝑗⟂𝑝𝑗𝑟𝑗⎞⎟
⎟
⎟
⎟⎠𝜑(𝑚)/𝜑(𝑝𝑒𝑗𝑗)(mod𝑝𝑒𝑗𝑗).
此处的指数 𝜑(𝑚)/𝜑(𝑝𝑒𝑗𝑗) =𝜑(𝑚/𝑝𝑒𝑗𝑗)
要成为奇数,必然要求 𝑚/𝑝𝑒𝑗𝑗 =1,2
,因为欧拉函数 𝜑(𝑛)
对于 𝑛 ≥3
都是偶数。如果 𝑝𝑗
是奇素数,因为模 𝑚
的原根不存在,必然有 𝑚/𝑝𝑒𝑗𝑗 ≠1,2
;如果 𝑝𝑒𝑗𝑗 =2,4
,因为模 𝑚
的原根不存在,必然有 𝑚/𝑝𝑒𝑗𝑗
含有某个奇素因子,故而大于 2
:这两种情形指数 𝜑(𝑚)/𝜑(𝑝𝑒𝑗𝑗)
都是偶数。而上式中括号里的项已经证明是模 𝑝𝑒𝑗𝑗
余 −1
的,所以这个幂模 𝑝𝑒𝑗𝑗
的余数一定是 1
。剩余的情形只有 𝑝𝑗 =2
且 𝑒𝑗 >2
时,对于这个情形,可以直接证明 `
∏1≤𝑟𝑗<2𝑒𝑗, 𝑟𝑗⟂2𝑟𝑗≡1(mod2𝑒𝑗).
仿照前文的证明思路,可以将所有 1 ≤𝑟𝑗 <2𝑒𝑗
的奇数 𝑟𝑗
两两配对而消去,那些无法配对的必然是方程 𝑥2 ≡1(mod2𝑒𝑗)
的解。该方程意味着 2𝑒𝑗 ∣(𝑥 −1)(𝑥 +1)
。令 𝑥 =2𝑦 +1
,就必然有 2𝑒𝑗−2 ∣𝑦(𝑦 +1)
,而 𝑦
和 𝑦 +1
必然一奇一偶,所以 𝑦 =𝑡2𝑒𝑗−2
或 𝑦 =𝑡2𝑒𝑗−2 −1
。故而,有 𝑥 =𝑡2𝑒𝑗−1 ±1
且 𝑡
是整数。模 2𝑒𝑗
的余数中,只有 ±1
和 2𝑒𝑗−1 ±1
四个。因此,有
∏1≤𝑟𝑗<2𝑒𝑗, 𝑟𝑗⟂2𝑟𝑗≡(−1)(2𝑒𝑗−1−1)(2𝑒𝑗−1+1)≡1(mod2𝑒𝑗).
这就完成了所有情形的证明。
在计算中,尤为重要的是模数为素数幂的情形:
推论
对于素数 𝑝
和正整数 𝛼
,有
$$
\prod_{1\le k
本页面最近更新:2025/10/13 16:54:57,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面贡献者:c-forrest, aofall, CoelacanthusHex, DanJoshua, Early0v0, Enter-tainer, Great-designer, iamtwz, Marcythm, Persdre, shuzhouliu, Tiphereth-A, wsyhb, Xeonacid
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用