威尔逊定理
定理
(p−1)!≡−1(modp)
证明
集合的差:A∖B={x∣x∈A∧x∈B}。
x 表示模 p 余 x 的数组成的集合。
当 p=2 时,命题显然成立。
以下设 p≥3,此时我们要证 Zp 中所有非零元素的积为 −1。
我们知道 Zp 中所有非零元素 a 都有逆元 a−1,于是 Zp 中彼此互逆的元素乘积为 1。
但是要注意 a 和 a−1 可能相等。若 a=a−1,则 a2≡1(modp),即
0≡a2−1≡(a+1)(a−1)(modp)
从而 a≡1(modp) 或 a≡−1(modp)。
这说明 Zp∖{0,1,−1} 中所有元素的乘积为 1, 进而 Zp 中所有非零元素的积为 −1。
应用
阶乘与素数
在某些情况下,有必要考虑以某个素数 p 为模的公式,包含分子和分母中的阶乘,就像在二项式系数公式中遇到的那样。
只有当阶乘同时出现在分数的分子和分母中时,这个问题才有意义。否则,后续项 p! 将减少为零。但在分数中,因子 p 可以抵消,结果将是非零。
因此,要计算 n!modp,而不考虑阶乘中出现因数 p。写下素因子分解,去掉所有因子 p,并计算乘积模。
用 (n!)p 表示这个修改的因子。例如:
(7!)p≡1⋅2⋅31⋅4⋅562⋅7≡2mod3
这种修正的阶乘,可用于快速计算各种带取模和组合数的公式的值(吗?)。
计算余数的算法
计算上述去掉因子 p 的阶乘模 p 的余数。
(n!)p =1⋅2⋅3⋅…⋅(p−2)⋅(p−1)⋅p1⋅(p+1)⋅(p+2)⋅…⋅(2p−1)⋅2p2⋅(2p+1)⋅…⋅(p2−1)⋅p21⋅(p2+1)⋅…⋅n(modp)=1⋅2⋅3⋅…⋅(p−2)⋅(p−1)⋅p1⋅1⋅2⋅…⋅(p−1)⋅2p2⋅1⋅2⋅…⋅(p−1)⋅p21⋅1⋅2⋅…⋅(nmodp)(modp)
可以清楚地看到,除了最后一个块外,阶乘被划分为几个长度相同的块。
(n!)p=1st1⋅2⋅3⋅…⋅(p−2)⋅(p−1)⋅1⋅2nd1⋅2⋅3⋅…⋅(p−2)⋅(p−1)⋅2⋅…⋅pth1⋅2⋅3⋅…⋅(p−2)⋅(p−1)⋅1⋅…⋅tail1⋅2⋅⋅…⋅(nmodp)(modp).
块的主要部分 (p−1)! mod p 很容易计算,可以应用 Wilson 定理:
(p−1)!≡−1(modp)
总共有 ⌊pn⌋ 个块,因此需要将 ⌊pn⌋ 写到 −1 的指数上。可以注意到结果在 −1 和 1 之间切换,因此只需要查看指数的奇偶性,如果是奇数,则乘以 −1。除了使用乘法,也可以从结果中减去 p。
最后一个部分块的值可以在 O(p) 的时间复杂度单独计算。
这只留下每个块的最后一个元素。如果隐藏已处理的元素,可以看到以下模式:
(n!)p=…⋅1⋅…⋅2⋅…⋅…⋅(p−1)⋅…⋅1⋅…⋅1⋅…⋅2⋯
这也是一个修正的阶乘,只是维数小得多。它是:
(⌊pn⌋!)p
因此,在计算修改的阶乘 (n!)p 中,执行了 O(p) 个操作,剩下的是计算 (⌊pn⌋!)p,于是有了递归,递归深度为 O(logpn),因此算法的总时间复杂度为 O(plogpn).
如果预先计算阶乘 0!,1!,2!,…,(p−1)! 模 p,那么时间复杂度为 O(logpn).
?
错排列
问题
设 a 是 1 到 n 的一个全排列,求满足 ∀i∈[1,n],ai=i 的排列数量。
解法
正难则反,求 ∃i∈[1,n],ai=i 的排列数。
于是令一个排列的相等的地方为 p,大小为 k(∀i∈[1,k],api=pi),显然,它对答案的贡献为 (n−k)!,观察到 p 中具体有哪些元素我们并不关心,我们只关心它有多少元素,可以得出答案为:
i=0∑n(−1)iCni(n−i)!=i=0∑n(−1)ii!n!
圆排列
问题
从 n 个不同元素中取出 m 个元素,不分首尾的围成一个圆的排列叫做圆排列,求其方案个数。
解法
笛卡尔树(没听到讲)
多重集的排列组合
严格次小生成树
树套树