0 写在前面
0.0 前言
由于我太菜了,导致一些东西一学就忘,特开此文来记录下最让我头痛的数学相关问题。
一些引用的文字都注释了原文链接,若侵犯了您的权益,敬请告知;若文章中出现错误,也烦请告知。
该文于 2018.3.31 完成最后一次修改(若有出错的地方,之后也会进行维护)。其主要内容限于数论和组合计数类数学相关问题。因为版面原因,其余数学方面的总结会以全新的博文呈现。
感谢你的造访。
0.1 记号说明
由于该文完成的间隔跨度太大,不同时期的内容的写法不严谨,甚至 $LaTeX$ 也有许多不规范的表达。我懒也不想改...请见谅...
1 数论
1.0 gcd
1.0.0 gcd
$gcd(a, b) = gcd(b, a \mod b)$
证明:设 $c \mid a, c \mid b$ ,则 $c \mid (b-a)$ 。
设 $c \nmid a$ ,则 $c$ 不是 $a,b-a$ 的公因子。
设 $c \mid a$ , $c \nmid b$ ,则 $c$ 不是 $a,b-a$ 的公因子。
1 int gcd(int a, int b) { 2 return b == 0 ? a : gcd(b, a%b); 3 }
1.0.1 exgcd
对于一组不定方程 $a \times x+b \times y = c$ 。若 $gcd(a, b) \mid c$ 则这组方程有无数组解,否则无解。
求出一组 $a \times x+b \times y = gcd(a, b)$的解需要$exgcd$,是在$gcd$递归函数过程中实现的。
设$x_0$,$y_0$是这一层的解,$x_1$,$y_1$是上一层的解。
首先边界条件:当$b = 0$时显然$x_0 = 1$,$y_0 = 0$。
其他情况下有:$x_0 = y_1$,$y_0 = x_1- \frac{a}{b} \times y_1$。
证明(摘自PIPIBoss):
$gcd(a, b) = x_0 \times a+y_0 \times b$$gcd(b, a \mod b) = x_1 \times b+y_1 \times (a \mod b) = x_1 \times b+y_1 \times (a-\frac{a}{b} \times b)$因为 $gcd(a, b) = gcd(b, a \mod b)$得 $x_0 \times a+y_0 \times b = x_1 \times b+y_1 \times (a-\frac{a}{b} \times b)$合并得 $x_0 \times a+y_0 \times b = y_1 \times a+(x_1-\frac{a}{b} \times y_1) \times b$根据恒等定理 $x_0 = y_1$,$y_0 = x_1-\frac{a}{b} \times y_1$
1 int exgcd(int a, int b, int &x, int &y) { 2 if (b == 0) { 3 x = 1; y = 0; 4 return a; 5 } 6 int c = exgcd(b, a%b, x, y); 7 int t = x; 8 x = y; 9 y = t-a/b*y; 10 return c; 11 }
1.1 逆元
对于正整数和,如果有,那么把这个同余方程中的最小正整数解叫做模的逆元。
逆元一般用扩展欧几里得算法来求得,如果为素数,那么还可以根据费马小定理得到逆元为。
推导过程如下:
另外,逆元还有线性算法:
首先,$1^{-1} ≡ 1(\mod p)$
然后,我们设$p=k \times i+r$,$r
$$k \times i+r ≡ 0(\mod p)$$
在等号两边同乘上$i^{-1}$,$r^{-1}$,就会得到:
$$k \times r^{-1}+i^{-1} ≡ 0(\mod p)$$
$$i^{-1} ≡ -k \times r^{-1}(\mod p)$$
$$i^{-1} ≡ -{\lfloor {p \over i} \rfloor} \times (p \mod i)^{-1}(\mod p)$$
递推代码就是:
1 A[i] = -(p/i)*A[p%i]
1.2 中国剩余定理(摘自MashiroSky)
1.2.0 中国剩余定理
在《孙子算经》中有这样一个问题:“今有物不知其数,三三数之剩二(除以3余2),五五数之剩三(除以5余3),七七数之剩二(除以7余2),问物几何?”这个问题称为“孙子问题”,该问题的一般解法国际上称为“中国剩余定理”。具体解法分三步:
-
- 找出三个数:从3和5的公倍数中找出被7除余1的最小数15,从3和7的公倍数中找出被5除余1 的最小数21,最后从5和7的公倍数中找出除3余1的最小数70。
- 用15乘以2(2为最终结果除以7的余数),用21乘以3(3为最终结果除以5的余数),同理,用70乘以2(2为最终结果除以3的余数),然后把三个乘积相加${15 \times 2+21 \times 3+70 \times 2}$得到和233。
- 用233除以3,5,7三个数的最小公倍数105,得到余数23,即${ 233\%105=23 }$。这个余数23就是符合条件的最小数。
就这么简单。我们在感叹神奇的同时不禁想知道古人是如何想到这个方法的,有什么基本的数学依据吗?
我们将“孙子问题”拆分成几个简单的小问题,从零开始,试图揣测古人是如何推导出这个解法的。
首先,我们假设${n_1}$是满足除以3余2的一个数,比如2,5,8等等,也就是满足${3 \times k+2(k>=0)}$的一个任意数。同样,我们假设${n_2}$是满足除以5余3的一个数,${n_3}$是满足除以7余2的一个数。
有了前面的假设,我们先从${n_1}$这个角度出发,已知${n_1}$满足除以3余2,能不能使得${n_1+n_2}$的和仍然满足除以3余2?进而使得${n_1+n_2+n_3}$的和仍然满足除以3余2?
这就牵涉到一个最基本数学定理,如果有${ a \% b=c }$,则有${ (a+k \times b) \% b=c(k为非零整数) }$,换句话说,如果一个除法运算的余数为${c}$,那么被除数与${k}$倍的除数相加(或相减)的和(差)再与除数相除,余数不变。这个是很好证明的。
以此定理为依据,如果${n_2}$是3的倍数,${n_1+n_2}$就依然满足除以3余2。同理,如果${n_3}$也是3的倍数,那么${n_1+n_2+n_3}$的和就满足除以3余2。这是从${n_1}$的角度考虑的,再从${n_2}$,${n_3}$的角度出发,我们可推导出以下三点:
-
- 为使${n_1+n_2+n_3}$的和满足除以3余2,${n_2}$和${n_3}$必须是3的倍数。
- 为使${n_1+n_2+n_3}$的和满足除以5余3,${n_1}$和${n_3}$必须是5的倍数。
- 为使${n_1+n_2+n_3}$的和满足除以7余2,${n_1}$和${n_2}$必须是7的倍数。
因此,为使${n_1+n_2+n_3}$的和作为“孙子问题”的一个最终解,需满足:
-
- ${n_1}$除以3余2,且是5和7的公倍数。
- ${n_2}$除以5余3,且是3和7的公倍数。
- ${n_3}$除以7余2,且是3和5的公倍数。
所以,孙子问题解法的本质是从5和7的公倍数中找一个除以3余2的数${n_1}$,从3和7的公倍数中找一个除以5余3的数${n_2}$,从3和5的公倍数中找一个除以7余2的数${n_3}$,再将三个数相加得到解。在求${n_1}$,${n_2}$,${n_3}$时又用了一个小技巧,以${n_1}$为例,并非从5和7的公倍数中直接找一个除以3余2的数,而是先找一个除以3余1的数,再乘以2。也就是先求出5和7的公倍数模3下的逆元,再用逆元去乘余数。
这里又有一个数学公式,如果${a \% b=c}$,那么${(a \times k) \% b=a \% b+a \% b+…+a \% b=c+c+…+c=k \times c(k>0)}$,也就是说,如果一个除法的余数为${c}$,那么被除数的${k}$倍与除数相除的余数为${k \times c}$。展开式中已证明。
最后,我们还要清楚一点,${n_1+n_2+n_3}$只是问题的一个解,并不是最小的解。如何得到最小解?我们只需要从中最大限度的减掉掉3,5,7的公倍数105即可。道理就是前面讲过的定理“如果${a \%b=c}$,则有${(a-k \times b) \% b=c}$”。所以${(n_1+n_2+n_3)\% 105}$就是最终的最小解。
这样一来就得到了中国剩余定理的公式:
设正整数两两互素,则同余方程组
有整数解。并且在模下的解是唯一的,解为
其中,而为模的逆元。
1 int ex_gcd(int a, int b, int &x, int &y) { 2 if (b == 0) { 3 x = 1, y = 0; return a; 4 } 5 int gcd = ex_gcd(b, a%b, x, y); 6 int t = x; 7 x = y; 8 y = t-a/b*y; 9 return gcd; 10 } 11 int inv(int a, int b) { 12 int x, y; 13 ex_gcd(a, b, x, y); 14 return (x%b+b)%b; 15 } 16 int CRT() { 17 int M = 1, ans = 0; 18 for (int i = 1; i <= n; i++) M *= m[i]; 19 for (int i = 1; i <= n; i++) 20 (ans += a[i]*(M/m[i])*inv(M/m[i], m[i])) %= M; 21 return (ans+M)%M; 22 }
1.2.1 扩展中国剩余定理*
普通的中国剩余定理要求所有的互素,那么如果不互素呢,怎么求解同余方程组?
这种情况就采用两两合并的思想,假设要合并如下两个方程:
那么得到:
我们需要求出一个最小的${x}$使它满足:
那么${x_1}$和${x_2}$就要尽可能的小,于是我们用扩展欧几里得算法求出${x_1}$的最小正整数解,将它代回${a_1+m_1x_1}$,得到${x}$的一个特解${x'}$,当然也是最小正整数解。
所以${x}$的通解一定是${x'}$加上${lcm(m1,m2) \times k}$,这样才能保证${x}$模${m_1}$和${m_2}$的余数是${a_1}$和${a_2}$。由此,我们把这个${x'}$当做新的方程的余数,把${lcm(m1,m2)}$当做新的方程的模数。(这一段是关键)
合并完成:
1.3 Catalan数(摘自Miskcoo)
1.3.0 带限制条件的路径总数
首先我们来看一个问题:
在一个平面直角坐标系中,只能往右或往上走一个单位长度,问有多少种不同的路径可以从左下角 走到右上角 ,并且要求路径不能经过直线 上方的点,下图中的路径都是合法的(图片来源 Wikipedia)
如果没有限制条件,那么从左下角走到右上角一共有 步,有 步是往右,另外 步是往上,那么路径方案数就是 步中选择 步往右,一共有 (即 )种方案
那么我们考虑一下这里面有多少种方案是不合法的
首先对于每一种不合法的方案,它的路径一定与 有交。我们找到它与 的第一个交点,然后将这个点后面部分的路径关于 做一个对称。由于原来路径到达 ,新的对称之后的路径就会到达 。这样我们把每一种不合法方案都对应到了一条从 到 的路径,现在再来看是否每一条这样的路径都能对应到一种不合法方案,如果是,那么这就建立了一个一一映射的关系,也就是它们的方案总数相同。这是肯定的,因为每一条这样的路径必定与 有交,那么对称回去,就得到一条不合法方案
由于从 到 的路径有 条,那么合法的方案就是
我们把这个方案数记为 ,这就是著名的 Catalan 数
我们来看看它的前几项( 从 开始)
1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190
1.3.1 括号序列计数
再来看一个问题:有多少种不同的长度为 的括号序列?
首先一个括号序列是指 (), ()(), (())() 这样的由括号组成的序列,并且没有左右括号无法匹配的情况
我们可以将长度为 的括号序列映射成刚刚所说的路径:首先对于左括号,那么就向右走一个单位长度,对于右括号,那么就向上走一个单位长度,由于括号序列合法,那么每次向右走的次数不会少于向上的次数,也就是这条路径不会在 之上。再考虑每一条这样的路径,也能够对应到一种合法的括号序列,因此,长度为 的括号序列的方案数就是
1.3.2 出栈顺序
现在来考虑你有 个元素(元素之间是没有区别的)和一个栈,每次可以将一个元素入栈,或者将栈顶元素弹出,问有多少种可能的操作序列,这可以将问题对应成括号序列,入栈为左括号,出栈为右括号,因此方案数也是
1.3.3 排队问题
现在有 个人,他们身高互不相同,他们要成两排,每一排有 个人,并且满足每一排必须是从矮到高,且后一排的人要比前一排对应的人要高,问有多少种排法
我们考虑先把这些人从矮到高排成一排,那么现在来分配哪个人在前,哪个人在后,例如有 个人,身高是 1, 2, 3, 4, 5, 6
那么我们用 1 表示这个人应该在后排,0 表示这个人应该在前排,例如说 100110 表示两排分别是 2, 3, 6 和 1, 4, 5 这是不合法的
那么合法方案应该是怎么样的呢?后排要比前排对应的人高,也就是说 0 的出现次数在每一个地方都不应该小于 1,这恰恰又是一个括号序列,因此,方案仍然是 Catalan 数
1.3.4 二叉树计数
现在你需要统计有多少种不同的 个结点的二叉树
图上的是 个结点的二叉树,一共有 种方案
朴素的想法是由于二叉树是递归定义的,可以考虑使用递推方法
我们可以用 表示有 个结点的二叉树的方案数(空树算一种,即 ),那么枚举子树大小可以得到方程
如果直接计算,你需要 的时间
现在我们换一个角度来想,对这棵二叉树进行遍历,并且考虑一个括号序列,当第一次遇到这个结点的时候,在括号序列末尾添加一个左括号,在从左子树回到这个结点的时候,在括号序列中添加一个右括号,这样,将每一种不同的二叉树都对应到了一种不同的括号序列,同样对于每一种不同的括号序列都可以找到对应的一种不同的二叉树,因此,有 个结点的二叉树的数量也是
生成函数的证明*
我们可以定义序列 的生成函数为 ,再根据上面的递推式,可以列出方程
解方程可以得到
因为 ,因此对上式求极限
因此取负号,
根据广义二项式定理展开
然后考虑第 项系数
因此可以得到
同样得到
1.4 素数
1.4.0 素数的相关定理
唯一分解定理
对任一整数 $a > 1$ ,有 $a={p_1}^{a_1}{p_2}^{a_2}…{p_n}^{a_n}$ ,其中 $p_1
约数和定理
对于唯一分解定理中的式子,满足 $a$ 的正约数个数为: $(1+a_1)(1+a_2)…(1+a_n)$
$a$ 的约数和个数为: $\prod_{i = 1}^n \sum_{j = 0}^{a_i} p_i^j$
威尔逊定理
若 $p$ 是素数,则 $(p-1)! \equiv -1 \pmod{p}$ 。
其逆定理也成立,即:若对某一正整数 $p$ ,有 $(p-1)! \equiv -1 \pmod{p}$ ,则 $p$ 一定是素数。
由于 $p \mid (p-1)!+1$ ,可以构造函数 $f(n) = \sin(\pi \cdot \frac{(n-1)!+1}{n})$ 。这个函数的零点都是素数,并且所有素数都是这个函数的零点。
费马小定理
若 $p$ 为素数, $a$ 为正整数,且 $a$ 和 $p$ 互素,则: $a^{p-1} \equiv 1 \pmod{p}$ 。
证明:首先, $p-1$ 个整数 $a,2a,3a,\cdots,(p-1)a$ 中没有一个是 $p$ 的倍数。
其次, $a,2a,3a,\cdots,(p-1)a$ 中没有任何两个同余于模 $p$ 的。
于是: $a,2a,3a,\cdots,(p-1)a$ 对模 $p$ 的同余既不为 $0$ ,也没有两个同余相同,因此,这 $p-1$ 个数对模 $p$ 的同余一定是 $1,2,3,\cdots,p-1$ 的某一种排列,即:$$a \cdot 2a \cdot 3a \cdot \cdots \cdot (p-1)a \equiv 1 \cdot 2 \cdot 3 \cdot \cdots \cdot (p-1) \pmod{p}$$
化简为: $$a^{p-1} \cdot (p-1)! \equiv (p-1)! \pmod{p}$$
由于模数 $p$ 是质数,根据威尔逊定理得出 $(p-1)!$ 和 $p$ 互质。所以约去 $(p-1)!$ 。
得到: $$a^{p-1} \equiv 1 \pmod{p}$$
欧拉定理
欧拉函数:记小于等于 $n$ 的数中与 $n$ 互质的数的个数为 $\varphi(n)$ 。
引理1:
①如果 $n$ 为某一个素数 $p$ ,则 $\varphi(p) = p-1$;
②如果 $n$ 为某一个素数 $p$ 的幂次 $p^a$ ,则 $\varphi(p^a) = (p-1) \cdot p^{a-1}$ ;
③如果 $n$ 为两个互质的数 $a,b$ 的乘积,则 $\varphi(ab) = \varphi(a) \cdot \varphi(b)$ 。
证明:①显然;
②因为比 $p^a$ 小的数有 $p^a-1$ 个,那么有 $p^{a-1}-1$ 个数能被 $p$ 所整除(因为把 $1 \sim p^a-1$ 的 $p$ 的倍数都筛去了),所以 $\varphi(p^a) = (p-1) \cdot p^{a-1}$ ;
③只有那些既满足 $a$ 与其互质且满足 $b$ 与其互质的数满足条件。根据乘法原理,这样的数可以互相组合,那么就有 $\varphi(a) \cdot \varphi(b)$ 个。
引理2:
设 $n = \prod_{i = 1}^k p_i^{a_i}$ 为正整数 $n$ 的素数幂乘积表示式。则 $$\varphi(n) = n \cdot \prod_{i = 1}^k \left(1-\frac{1}{p_i} \right)$$
证明:
\begin{aligned} \varphi(n) &= \prod_{i = 1}^k \varphi(p_i^{a_i})\\&= \prod_{i = 1}^k p_i^{a_i}\cdot \left(1-\frac{1}{p_i} \right)\\&= n \cdot \prod_{i = 1}^k \left(1-\frac{1}{p_i} \right)\end{aligned}
欧拉定理:若 $a$ 与 $m$ 互质,则 $a^{\varphi(m)} \equiv 1 \pmod{m}$ 。
证明:
按照证明费马小定理思路:
将小于 $m$ 的 $\varphi(m)$ 个与 $m$ 互质的整数取出,为 $x_1,x_2,\cdots,x_{\varphi(m)}$ 。
取出 $\varphi(m)$ 个整数 $x_1a,x_2a,\cdots,x_{\varphi(m)}a$ ,其中没有一个是 $m$ 的倍数,也没有两个模 $m$ 同余的。
简要证明:假设 $x_ia \equiv x_ja \pmod m$ (假设 $x_i > x_j$ )。显然 $(x_i-x_j)a \equiv 0 \pmod m$ ,即 $m \mid (x_i-x_j)a$ ,由于 $gcd(a, m) = 1$ 且 $(x_i-x_j) < m$ ,则 $m \nmid (x_i-x_j)a$ ,矛盾,原命题成立。
又因为 $x_1a,x_2a,\cdots,x_{\varphi(m)}a$ 在模 $m$ 意义下均与 $m$ 互素。
简要证明:记 $x_ia \equiv b \pmod{m}$ ,假设 $b$ 不互素,显然 $gcd(b, m) = d \neq 1$ , $b = k_1 \cdot d, m = k_2 \cdot d$ ,由于 $x_ia = b+K'm$ ,即 $x_ia = (k_1+K'k_2) \cdot d$ ,则 $x_ia$ 与 $m$ 有共同因子 $d$ ,但由于 $a, x_i$ 均与 $m$ 互素,矛盾,原命题成立。
有上述两个定理,故 $x_1a,x_2a,\cdots,x_{\varphi(m)}a$ 在模 $m$ 意义下是 $x_1,x_2,\cdots,x_{\varphi(m)}$ 的一个排列。
故有: $$x_1a\cdot x_2a\cdot\cdots\cdot x_{\varphi(m)}a \equiv x_1\cdot x_2\cdot\cdots\cdot x_{\varphi(m)} \pmod{m}$$
化简为: $$a^{\varphi(m)}\cdot x_1\cdot x_2\cdot\cdots\cdot x_{\varphi(m)} \equiv x_1\cdot x_2\cdot\cdot\cdot x_{\varphi(m)} \pmod{m}$$
由于 $x_1,x_2,\cdots,x_{\varphi(m)}$ 均与 $m$ 互质,所以可以约去,得: $$a^{\varphi(m)} \equiv 1 \pmod{m}$$
线性筛欧拉函数
用到的性质(其中 $p$ 为素数):
① $\varphi(p) = p-1$ ;
②如果 $p \mid i$ ,那么 $\varphi(i \cdot p) = p\cdot \varphi(i)$ ;
③如果 $p \nmid i$ ,那么 $\varphi(i \cdot p) = (p-1)\cdot \varphi(i)$ 。
证明:①显然;
②由于 $p \mid i$ ,显然 $i$ 与 $i \cdot p$ 间没有不同的因子。
则对于一个整数 $x$ ,若 $gcd(x,i) = 1$ 则 $gcd(x,i \cdot p) = 1$ 。
我们将从 $0$ 开始长度为 $i \cdot p$ 的数轴分成 $p$ 段长度为 $i$ 的小段。对于第一段为 $[1,i]$ ,第二段为 $[i+1, i+i]$ ……以此类推。
对于第一段中,与 $i$ 互质的数有 $\varphi(i)$ 个。即在第一段中与 $i \cdot p$ 互质的数也有 $\varphi(i)$ 个。
现在我们证明对于整数 $x$ 若与 $i$ 互质,则 $x+i$ 也与 $i$ 互质。
采用反证法,我们假设 $gcd(x, i) = 1$ 但 $gcd(x+i, i) = b \neq 1$ 。
容易发现: \begin{cases} \begin{aligned} x+i = b\cdot k_1 \\ i = b \cdot k_2 \end{aligned} \end{cases} $k_1,k_2$ 均为整数。
所以 $x = (k_1-k_2)\cdot b$ ,故 $gcd(x, i) = b \neq 1$ ,与题设不符,原命题成立。
下证对于整数 $x$ 若与 $i$ 不互质,则 $x+i$ 也与 $i$ 不互质。
假设 $gcd(x, i) = b \neq 1$ , \begin{cases} \begin{aligned} x = b\cdot k_1 \\ i = b \cdot k_2 \end{aligned} \end{cases}$k_1,k_2$ 均为整数。
所以 $x+i = (k_1+k_2)\cdot b$ ,故 $gcd(x+i, i) = b \neq 1$ ,原命题成立。
综上,如果 $p \mid i$ ,那么 $\varphi(i \cdot p) = p\cdot \varphi(i)$ ;③因为 $p \nmid i$ ,且 $p$ 为质数,所以 $i$ 与 $p$ 互质,由于欧拉函数是积性函数, $\varphi(i \cdot p) = \varphi(p)\cdot \varphi(i)$ ,又 $\varphi(p) = p-1$ 。
1 void get_phi() { 2 memset(isprime, 1, sizeof(isprime)); isprime[1] = 0; phi[1] = 1; 3 for (int i = 2; i <= n; i++) { 4 if (isprime[i]) phi[i] = i-1, prime[++tot] = i; 5 for (int j = 1; j <= tot && i*prime[j] <= n; j++) { 6 isprime[i*prime[j]] = 0; 7 if (!(i%prime[j])) {phi[i*prime[j]] = phi[i]*prime[j]; break; } 8 else phi[i*prime[j]] = phi[prime[j]]*phi[i]; 9 } 10 } 11 }
扩展欧拉定理:$a^q \equiv a^{q\ mod\ \varphi(m)+\varphi(m)} \pmod{m}$ ,其中 $a,m \in \mathbb{Z}^*$
证明(摘自: )
要证明扩展欧拉定理则只需证a的任意一个质因子 ,
简单解释一下这是如何转化的。
根据同余式可乘可推公式二出
即
根据同余式可乘得到
可以发现这就是
那么现在要证明的东西已经转化, 考虑如何证得。
为 某质因子, 若 则由欧拉定理显然证得, 考虑
则 (因为 和 互质, 由欧拉定理可得)
由欧拉函数的积性
所以
从而
显然式子同时乘以 得到
因为
显然 所以两边同时乘以 可以得到上面转化出来要求的式子
证毕。
1.4.1 降幂大法
$$a^b\equiv
\begin{cases}
a^{b\ mod \ \varphi(p)}~~~~~~~~~~~gcd(a,p)=1\\
a^b~~~~~~~~~~~~~~~~~~~~~gcd(a,p)\neq1,b<\varphi(p)\\
a^{b\ mod \ \varphi(p)+\varphi(p)}~~~~gcd(a,p)\neq1,b\geq\varphi(p)
\end{cases}\pmod{p}$$
1.4.2 Miller-Rabin 素数测试
主要利用费马小定理 $a^{p-1} \equiv 1 \pmod{p}$ ,实现的过程如下:
-
- 计算奇数 $M$ ,使得 $N = 2^r \times M+1$
- 选择随机数 $A < N$
- 对于任意 $i < r$ ,若 $A^{2^i \times M}~mod~N = N-1$ ,则 $N$ 通过随机数 $A$ 的测试
- 或者,若 $A^M~mod~N = 1$ ,则 $N$ 通过随机数 $A$ 的测试
- 让 $A$ 取不同的值对 $N$ 进行 $5$ 次测试,若全部通过则判定 $N$ 为素数
而在实际运用中,我们可以直接取 $r = 0$ ,从而省去步骤 $3$ 的测试,提高速度;另外的可以首先用几个小素数对 $N$ 进行测试。除此之外也可以引入“二次探测”的思想,防止被 Carmichael数 卡。
二次探测:对于一个奇素数 $p$ ,对于关于 $x$ 的同余方程 $x^2 \equiv 1 \pmod{p}$ ,在 $[1, p)$ 上的解仅有 $x = 1$ 及 $x = p-1$ 。
1 const int prime[10] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29}; 2 3 LL quick_multi(LL a, LL b, LL p) { 4 LL ans = 0; 5 while (b) { 6 if (b&1) ans = (ans+a)%p; 7 a = (a+a)%p, b >>= 1; 8 } 9 return ans; 10 } 11 LL quick_pow(LL a, LL b, LL p) { 12 LL ans = 1; 13 while (b) { 14 if (b&1) ans = quick_multi(ans, a, p); 15 a = quick_multi(a, a, p), b >>= 1; 16 } 17 return ans; 18 } 19 bool Miller_Rabin(LL x) { 20 if (x == 1) return false; 21 for (int i = 0; i < 10; i++) { 22 if (x == prime[i]) return true; 23 if (!(x%prime[i])) return false; 24 } 25 LL m = x-1, k = 0; 26 while (!(m&1)) m >>= 1, ++k; 27 for (int i = 0; i < 10; i++) { 28 LL a = rand()%(x-2)+2, pre = quick_pow(a, m, x), y; 29 for (int j = 0; j < k; j++) { 30 y = quick_multi(pre, pre, x); 31 if (y == 1 && pre != 1 && pre != x-1) return false; 32 pre = y; 33 } 34 if (pre != 1) return false; 35 } 36 return true; 37 }
1.4.3 Pollard-Rho 分解大数因子
代码为求一个大数的最小质因数(POJ 1811):
1 LL Pollard_Rho(LL x, int c) { 2 LL i = 1, k = 2, a1, a2; 3 a1 = a2 = rand()%(x-1)+1; 4 while (true) { 5 ++i, a1 = (quick_multi(a1, a1, x)+c)%x; 6 LL d = gcd(Abs(a1-a2), x); 7 if (1 < d && d < x) return d; 8 if (a1 == a2) return x; 9 if (i == k) a2 = a1, k <<= 1; 10 } 11 } 12 void find(LL x, int c) { 13 if (x == 1) return; 14 if (Miller_Rabin(x)) {ans = Min(ans, x); return; } 15 LL p = x, k = c; 16 while (p == x) p = Pollard_Rho(x, c--); 17 find(p, k), find(x/p, k); 18 }
1.4.4 Baby-Step-Giant-Step
1 LL BSGS(LL a, LL b, LL c) { 2 if (b == 1) return 0; 3 if (a == 0 && b != 0) return -1; 4 mp.clear(); 5 LL tim = ceil(sqrt((double)c)), tmp = b%c; 6 for (int i = 0; i <= tim; i++) { 7 mp.insert(tmp, i); tmp = tmp*a%c; 8 } 9 LL t = tmp = quick_pow(a, tim, c); 10 for (int i = 1; i <= tim; i++) { 11 if (mp.count(tmp)) return tim*i-mp.query(tmp); 12 tmp = tmp*t%c; 13 } 14 return -1; 15 }
扩展BSGS:
当模数 $c$ 不是质数的时候,显然不能直接使用 $BSGS$ 了,考虑它的扩展算法。
前提:同余性质。
令 $d = gcd(A, C)$ , $A = a \cdot d,B = b \cdot d, C = c \cdot d$
则 $a \cdot d \equiv b \cdot d \pmod{c \cdot d}$
等价于 $a \equiv b \pmod{c}$
因此我们可以先消除因子。
对于现在的问题 $(a \cdot d)^x \equiv b \cdot d \pmod{c \cdot d}$ 当我们提出 $d = gcd(A, C)$ ($d \neq 1$)后,原式化为 $a \cdot (a \cdot d)^{x-1} \equiv b \pmod{c}$ 。
即求 $D \cdot A^{x-cnt} \equiv b \pmod{c}$ ,令 $x = i \cdot r-j+cnt$ , $r$ 是块大小, $i,j\in \mathbb{Z}$ 。之后的做法就和 $BSGS$ 一样了。
值得注意的是因为这样求出来的解 $x \geq cnt$ 的,但有可能存在解 $x < cnt$ ,所以一开始需要特判。
1 LL exBSGS(LL a, LL b, LL c) { 2 if (b == 1) return 0; 3 if (a == 0 && b != 0) return -1; 4 LL cnt = 0, d = 1, t; 5 while ((t = gcd(a, c)) != 1) { 6 if (b%t) return -1; 7 ++cnt, b /= t, c /= t, d = d*(a/t)%c; 8 if (d == b) return cnt; 9 } 10 mp.clear(); 11 LL tim = ceil(sqrt(c)), tmp = b%c; 12 for (int i = 0; i <= tim; i++) { 13 mp.insert(tmp, i); tmp = tmp*a%c; 14 } 15 t = tmp = quick_pow(a, tim, c); tmp = (tmp*d)%c; 16 for (int i = 1; i <= tim; i++) { 17 if (mp.count(tmp)) return tim*i-mp.query(tmp)+cnt; 18 tmp = tmp*t%c; 19 } 20 return -1; 21 }
2 组合数学
2.0 一些公式
无重复的排列 $A_n^m = \frac{n!}{(n-m)!}$
无重复的组合 $C_n^m = \frac{A_n^m}{A_m^m} = \frac{n!}{m!(n-m)!}$
可重复的排列 $n^m$
可重复的组合 $C_{n+m-1}^m$
证明:用 $1,2,3,\cdots,n$ 表示 $n$ 个不同元素,这时从这 $n$ 个不同元素中取 $m$ 个元素的可重复组合具有下列形式: $$\{i_1,i_2,\cdots,i_m \},(1 \leq i_1 \leq i_2 \leq \cdots \leq i_m \leq n)$$
在上述每个数从左至右逐个分别加上: $0,1,\cdots,m-1$ ,得到 $\{j_1,j_2,\cdots,j_m \}$ ,其中 $j_1 = i_1, j_2 = i_2+1,\cdots ,j_m = i_m+(m-1)$ ,满足 $1 \leq j_1 < j_2 < \cdots < j_m \leq n+m-1$ ,而 $\{j_1,j_2,\cdots,j_m \}$ 恰好是从 $1,2,\cdots,n+m-1$ 这 $n+m-1$ 个元素中取 $m$ 个不同元素。
不全相异元素的全排列 如果 $n$ 个元素中,分别有 $n_1,n_2,\cdots,n_k$ 个元素相同,且 $n_1+n_2+\cdots+n_k = n$ ,则这 $n$ 个元素的全排列称为不全相异元素的全排列,其不同的排列个数记为 $\binom{n}{n_1~~n_2~~\cdots~~n_k}$ ,则 $\binom{n}{n_1~~n_2~~\cdots~~n_k} = \frac{n!}{n_1!n_2!\cdots n_k!}$ 。
证明:假设满足条件的排列数为 $f$ ,显然 $f\cdot n_1! \cdot n_2! \cdot \cdots \cdot n_k! = n!$ 。故 $f = \frac{n!}{n_1!n_2!\cdots n_k!} = \binom{n}{n_1~~n_2~~\cdots~~n_k}$ 。
多组组合 把 $n$ 个元素分为 $k(k \leq n)$ 个按照一定顺序排列的组,其中第 $i$ 组有 $n_i$ 个元素($i = 1,2,\cdots,k$ , $n_1+n_2+\cdots+n_k = n$),则不同的分组方法的种数为 $\binom{n}{n_1~~n_2~~\cdots~~n_k} = \frac{n!}{n_1!n_2!\cdots n_k!}$ 。
证明:
\begin{aligned}
&~~~~C_n^{n_1}\cdot C_{n-n_1}^{n_2}\cdot \cdots \cdot C_{n-n_1-n_2-\cdots-n_{k-1}}^{n_k}\\ &= \frac{n!}{n_1!\cdot(n-n_1)!}\cdot \frac{(n-n_1)!}{n_2!\cdot(n-n_1-n_2)!}\cdot \cdots \cdot \frac{(n-n_1-\cdots -n_{k-1})!}{n_k!\cdot(n-n_1-\cdots -n_{k-1}-n_k)!}\\&=\frac{n!}{n_1!n_2!\cdots n_k!}
\end{aligned}
圆排列 将 $n$ 个不同元素不分首尾排成一圈,称为 $n$ 个相异元素的圆排列,其排列种数为 $(n-1)!$ 。
项链数 将 $n$ 粒不同的珠子用线串成一副项链,则得到的不同项链数为 \begin{cases} 1& \text{$n \in \{1,2\}$}\\ \frac{1}{2}\cdot(n-1)!& \text{$n \in [3,+\infty)$} \end{cases}
一类不定方程的非负整数解的个数 不定方程 $x_1+x_2+\cdots+x_m = n~(m,n \in \mathbb{N}_+)$ 的非负整数解的个数为 $C_{n+m-1}^{m-1}$ 。推论:上述不定方程的正整数解的个数为 $C_{n-1}^{m-1}$ 。
证明:均可用“隔板法”证明,推论还需用“垫球法”。
容斥原理 设 $A_1,A_2,\cdots,A_n$ 为有限集合,用 $|A_i|$ 表示集合 $A_i$ 中的元素个数,那么
$$|A_1 \cup A_2 \cup \cdots \cup A_n| = \sum_{i=1}^n |A_i|-\sum_{1\leq i< j\leq n} |A_i\cap A_j|+\sum_{1\leq i< j< k\leq n} |A_i\cap A_j \cap A_k|-\cdots +(-1)^{n-1} |A_1\cap A_2 \cdots \cap A_n|$$
证明:若 $a \in A_1 \cup A_2 \cup \cdots \cup A_n$ ,则 $a$ 至少属于 $A_1,A_2,\cdots,A_n$ 中一个集合。不妨设 $a$ 属于 $A_1,A_2,\cdots,A_k~(1\leq k\leq n)$ 而不属于其他集合。于是 $a$ 在上式左端计算了一次。而 $a$ 在右端共计算的次数为
\begin{aligned} &~~~~C_k^1-C_k^2+C_k^3-\cdots+(-1)^{k-1}C_k^k\\ &= C_k^0-(C_k^0-C_k^1+\cdots+(-1)^kC_k^k)\\ &= 1-(1-1)^k \\ &= 1 \end{aligned}若 $a \notin A_1 \cup A_2 \cup \cdots \cup A_n$ ,则 $a$ 在上式左右两端计算的次数都为 $0$ 。原式成立。
筛法公式 设 $S$ 是有限集合, $A_i \subset S~(i=1,2,\cdots,n)$ , $A_i$ 在 $S$ 中的补集为 $\complement_S A_i~(i=1,2,\cdots,n)$ 则
$$|\complement_SA_1\cap\complement_SA_2\cap\cdots\cap\complement_SA_n| = |S|-\sum_{i=1}^n |A_i|+\sum_{1\leq i< j\leq n} |A_i\cap A_j|-\sum_{1\leq i< j< k\leq n} |A_i\cap A_j \cap A_k|+\cdots +(-1)^n |A_1\cap A_2 \cdots \cap A_n|$$
证明:因为 $|A_1 \cup A_2 \cup \cdots \cup A_n|=|S|-|\complement_S(A_1 \cup A_2 \cup \cdots \cup A_n)|$ ,并且由德·摩根律,我们有 $\complement_S(A_1 \cup A_2 \cup \cdots \cup A_n)=\complement_SA_1\cap\complement_SA_2\cap\cdots\cap\complement_SA_n$ 。再加上容斥原理的式子,得证。
错排公式 $D_n = n!\left(1-\frac{1}{1!}+\frac{1}{2!}-\frac{1}{3!}+\cdots+(-1)^n\frac{1}{n!}\right)$
置换及其不动点 给定集合 $X=\{1,2,\cdots,n\}$ , $\varphi$ 是从 $X$ 到 $X$ 上的一一映射,通常记为
$$\varphi = \left\{^{~~~~1~~~~~~2~~~~~~\cdots~~~~~~n~~~~}_{\varphi(1)~~\varphi(2)~~~~\cdots~~~~\varphi(n)}\right\}$$
则称 $\varphi$ 是 $X$ 上的置换,其中 $\varphi(i)$ 是元素 $i$ 在映射 $\varphi$ 下的象。因为是一一映射,所以 $\varphi(1),\varphi(2),\cdots,\varphi(n)$ 实际上是 $1,2,\cdots,n$ 的一个排列。满足 $\varphi(i) = i$ 的数 $i$ 称为 $\varphi$ 的一个不动点。容易证明,集合 $X$ 上没有任何不动点的置换 $\varphi$ 的个数是 $D_n = n!\left(1-\frac{1}{1!}+\frac{1}{2!}-\frac{1}{3!}+\cdots+(-1)^n\frac{1}{n!}\right)$ 。
第一抽屉原理 如果将 $m$ 个物品放入 $n$ 个抽屉内,那么必有一个抽屉内至少有 $\left\lfloor \frac{m-1}{n}\right\rfloor+1$ 个物品。
第二抽屉原理 如果将 $m$ 个物品放入 $n$ 个抽屉内,那么必有一个抽屉内至多有 $\left\lfloor \frac{m}{n}\right\rfloor$ 个物品。
2.1 母函数
2.1.0 概念
设 $f(x) = (1+x)^n$ ,由二项式定理,有 $$f(x) = \sum_{k=0}^n C_n^kx^k=C_n^0+C_n^1x+C_n^2x^2+\cdots+C_n^nx^n$$
这时, $f(x)$ 对应了一个数列 $\{C_n^k,0\leq k\leq n\}$ ,即生成数列 $\{C_n^k\}$ ,因此,我们把函数 $f(x) = (1+x)^n$ 称为数列 $\{C_n^k\}$ 的生成函数或母函数。
一般地说,对于有穷数列 $$a_0,a_1,a_2,\cdots,a_n$$
多项式 $f(x) = \sum_{k=0}^n a_kx^k=a_0+a_1x+a_2x^2+\cdots+a_nx^n$ 称为数列 $\{a_k\}$ 的母函数。
更一般地,对于无穷数列 $$a_0,a_1,\cdots,a_n,\cdots$$
我们称下列形式幂级数 $$f(x) = \sum_{n=0}^\infty a_nx^n=a_0+a_1x+\cdots+a_nx^n+\cdots$$
为无穷数列 $\{a_n\}$ 的母函数。
关于形式幂级数我们作如下的规定:设 $f(x) = \sum_{n=0}^\infty a_nx^n$ , $g(x) = \sum_{n=0}^\infty b_nx^n$ 是两个形式幂级数,我们规定
(1) $f(x)=g(x)$ ,当且仅当 $a_n=b_n~(n=0,1,2,\cdots)$ ;
(2) $f(x) \pm g(x) = \sum_{n=0}^\infty(a_n\pm b_n)x^n$ ;
(3) $\alpha f(x) = \sum_{n=0}^\infty(\alpha a_n)x^n$ , $\alpha$ 为常数;
(4) $f(x)g(x) = \sum_{n=0}^\infty c_nx^n$ ,其中 $c_n = \sum_{k=0}^na_kb_{n-k},n=0,1,2,\cdots$ 。
2.1.1 公式
公式一(无穷递缩等比数列求和公式) $$\frac{1}{1-x}=\sum_{n=0}^\infty x^n=1+x+x^2+\cdots+x^n+\cdots(|x|<1)$$
公式二 $$(1-x)^{-k}=\sum_{n=0}^\infty C_{n+k-1}^{k-1}x^n=1+C_{k}^{k-1}x+C_{k+1}^{k-1}x^2+\cdots+C_{n+k-1}^{k-1}x^n+\cdots(k \in \mathbb{Z}^*,|x|<1)$$
证明:公式二可由公式一两边求 $k-1$ 阶导数后除以 $(k-1)!$ 而得到。
2.2 莫比乌斯反演
2.2.0 莫比乌斯函数
莫比乌斯函数,是一个积性函数,记作 $\mu$ ,它的定义如下:
(1)若 $d = 1$ ,那么 $\mu(d)=1$
(2)若 $d=p_1p_2\cdots p_k$ , $p_i$ 均为互异素数,那么 $\mu(d)=(-1)^k$
(3)其他情况下 $\mu(d)=0$
性质:对于 $\forall n \in \mathbb{N}_+$
$$\sum_{d\mid n} \mu(d)=\begin{cases} 1 &n=1\\0 &n>1\end{cases}$$
证明:1. $n=1$ 时显然成立;
2. $n>1$ 时,将 $n$ 分解为 $p_1^{a_1}p_2^{a_2}\cdots p_k^{a_k}$ , $\mu(d)\neq 0$ 的只有次数均为 $1$ 的因子,其中质因数个数为 $i$ 的因子个数有 $C_k^i$ 个。
那么就有 \begin{aligned}\sum_{d\mid n} \mu(d)&=C_k^0-C_k^1+\cdots+(-1)^kC_k^k\\&=(1-1)^k=0 \end{aligned}
线性筛莫比乌斯函数
1 void get_mu() { 2 memset(isprime, 1, sizeof(isprime)); isprime[1] = 0, mu[1] = 1; 3 for (int i = 2; i <= N; i++) { 4 if (isprime[i]) prime[++tot] = i, mu[i] = -1; 5 for (int j = 1; j <= tot && i*prime[j] <= N; j++) { 6 isprime[i*prime[j]] = 0; 7 if (!(i%prime[j])) {mu[i*prime[j]] = 0; break; } 8 else mu[i*prime[j]] = -mu[i]; 9 } 10 } 11 }
2.2.1 莫比乌斯反演定理
若 $F(n)$ 和 $f(n)$ 是定义在非负整数集合上的两个函数,并且满足条件 $F(n)=\sum_{d\mid n} f(d)$ 。那么我们得到结论: $$f(n)=\sum_{d\mid n} \mu(d)F(\frac{n}{d})$$
证明: $$\sum_{d|n}\mu(d)F(\frac{n}{d})=\sum_{d|n}\mu(d)\sum_{k|\frac{n}{d}}f(k)=\sum_{k|n}f(k)\sum_{d|\frac{n}{k}}\mu(d)=f(n)$$
由这个定理我们可以得到莫比乌斯函数的另外一个性质: 对于$\forall n \in \mathbb{N}_+$
$$\sum_{d\mid n} \frac{\mu(d)}{d}=\frac{\varphi(n)}{n}$$
证明:
引理: $n=\sum_{d\mid n} \varphi(d)$
证明:
对于 $n$ 的每个因数 $d$ ,我们取出 $[1,d]$ 内的 $\varphi(d)$ 个与 $n$ 互素的数记做集合 $A=\{a_1,a_2,\cdots,a_{\varphi(d)}\}$ ,将集合 $A$ 内的元素对应到集合 $B=\{a_1\frac{n}{d},a_2\frac{n}{d},\cdots,a_{\varphi(d)}\frac{n}{d}\}$ 。显然 $gcd(a_i\frac{n}{d},n)=\frac{n}{d}$ 。由于 $d$ 枚举了所有 $n$ 的因数,所以 $\frac{n}{d}$ 也是。则集合 $B$ 内是 $[1,n]$ 内所有的数。故原命题成立。
有了这个引理,我们将莫比乌斯反演定理中的 $F(n) = n,f(n) = \varphi(n)$ 。 \begin{aligned}\varphi(n)&=\sum_{d\mid n} \frac{n}{d}\mu(d)\\ \frac{\varphi(n)}{n}&=\sum_{d\mid n} \frac{\mu(d)}{d} \end{aligned}
第二形式: $$F(n)=\sum_{n\mid d} f(d)\Rightarrow f(n)=\sum_{n\mid d} \mu(\frac{d}{n})F(d)$$
证明:令 $k=\frac{d}{n}$ ,那么 $$\sum^{+\infty}_{k=1}\mu(k)F(nk)=\sum^{+\infty}_{k=1}\mu(k)\sum_{nk|t}f(t)=\sum_{n|t}f(t)\sum_{k|\frac{t}{n}}\mu(k)=f(n)$$
2.2.2 杜教筛(普适)
若 $f(n)$ 是一个积性函数,求 $f(n)$ 的前缀 $S(n)$ 。即 $S(n)=\sum\limits_{i=1}^nf(n)$ 。
狄利克雷卷积
对于数论函数 $g(n),f(n)$ ,其狄利克雷卷积 $h(n)$ 也是一个数论函数 $$h(n)=\sum_{d\mid n}g(d)f\left(\frac{n}{d}\right)$$
我们找到另一个积性函数 $g(n)$ ,让 $f(n)$ 和 $g(n)$ 做一个卷积 $$(g*f)(n)=\sum_{d\mid n}g(d)f\left(\frac{n}{d}\right)$$
求卷积的前缀 $$\sum_{i=1}^n(g*f)(i)=\sum_{i=1}^n\sum_{d|i}g(d)f\left(\frac{i}{d}\right)$$
提出右式的 $d$ \begin{aligned}\Rightarrow\sum_{i=1}^n(g*f)(i)&=\sum_{d=1}^{n}g(d)\sum_{d|i}f\left(\frac{i}{d}\right)\\&=\sum_{d=1}^{n}g(d)\sum_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor}f(i)\\&=\sum_{d=1}^{n}g(d)S\left(\left\lfloor\frac{n}{d}\right\rfloor\right)\end{aligned}
容易得到这个式子 $$g(1)S(n)=\sum_{i=1}^ng(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)-\sum_{i=2}^ng(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)$$
其实就是 $$g(1)S(n)=\sum_{i=1}^n(g*f)(i)-\sum_{i=2}^ng(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)$$
我们发现如果狄利克雷卷积前缀很好算的话,积性函数的前缀也可以分块递归来算了。
举几个例子:
1. 求 $S(n)=\sum\limits_{i=1}^n\mu(n)$
上述式子 $$g(1)S(n)=\sum_{i=1}^n(g*\mu)(i)-\sum_{i=2}^ng(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)$$
考虑到 $\sum\limits_{d\mid n}\mu(d)=[n=1]$ ,又由于 $(g*\mu)(n)=\sum\limits_{d\mid n}g(d)\mu\left(\frac{n}{d}\right)$ 。我们考虑让 $g(n)=1(n)$ ,那么 $(1*\mu)(n)=\sum\limits_{d\mid n}1\cdot\mu(d)=[n=1]$ 。显然这个卷积的前缀为 $\sum\limits_{i=1}^n(g*\mu)(i)=1(n)$ 。
故对于 $\mu$ $$S(n)=1-\sum_{i=2}^nS\left(\left\lfloor\frac{n}{i}\right\rfloor\right)$$
2. 求 $S(n)=\sum\limits_{i=1}^n\varphi(n)$
上述式子 $$g(1)S(n)=\sum_{i=1}^n(g*\varphi)(i)-\sum_{i=2}^ng(i)S\left(\left\lfloor\frac{n}{i}\right\rfloor\right)$$
考虑到 $\sum\limits_{d\mid n}\varphi(d)=n$ ,又由于 $(g*\varphi)(n)=\sum\limits_{d\mid n}g(d)\varphi\left(\frac{n}{d}\right)$ 。我们考虑让 $g(n)=1(n)$ ,那么 $(1*\varphi)(n)=\sum\limits_{d\mid n}1\cdot\varphi(d)=n$ 。显然这个卷积的前缀为 $\sum\limits_{i=1}^n(g*\varphi)(i)=\frac{n(n+1)}{2}$ 。
故对于 $\varphi$ $$S(n)=\frac{n(n+1)}{2}-\sum_{i=2}^nS\left(\left\lfloor\frac{n}{i}\right\rfloor\right)$$
2.3 二项式系数
证明:由当 $a = b = 1$ 时,代入二项式定理可证明 $1$ 式;当 $a = -1$ , $b = 1$ 时代入二项式定理可证明 $2$ 式;代入 $a = 1$ , $b = -1$ 可得到另一个意义相同的式子;$(1式+2式) \over 2$ 可证明 $3$ 式。
2.4 Lucas定理
2.4.0 Lucas
$C^m_n\equiv C^{\left\lfloor\frac{m}{p}\right\rfloor}_{\left\lfloor\frac{n}{p}\right\rfloor} \times C^{m \mod p} _{n \mod p} \pmod{p}$ , $p$ 为质数。
证明:需要用到多项式同余的那套理论,然而我并不会。
2.4.1 扩展 Lucas
一般的 $Lucas$ 是在模数 $p$ 是质数的条件下适用的。我们来考虑 $p$ 不是质数的条件。
我们对 $p$ 进行唯一分解,记 $p=p_1^{k_1}p_2^{k_2}\cdots p_q^{k_q}$ ,由于形同 $p_i^{k_i}$ 的部分是互质的,显然我们可以用 $CRT$ 合并。
列出方程组: $\left\{ \begin{array}{c} ans\equiv c_1\pmod {{p_1}^{k_1}}\\ ans\equiv c_2\pmod {{p_2}^{k_2}}\\ ...\\ ans\equiv c_q\pmod {{p_q}^{k_q}}\\ \end{array} \right. $ ,对于每个 $c_i$ ,表示 $C_n^m$ 在 $\mod p_i^{k_i}$ 下的结果。由解的唯一性,我们可以证明这个 $ans$ 就是我们要求的。
根据 $C_n^m=\frac{n!}{m!(n-m)!}$ 我们只要求出 $n!\mod p_i^{k_i},m!\mod p_i^{k_i},(n-m)!\mod p_i^{k_i}$ ,再用逆元的那套理论就可以求 $c_i$ 了。
考虑如何求 $n!\mod p_i^{k_i}$ 。容易发现 $n!=\left(\prod\limits_{j=1}^n j^{[p_i\nmid j]}\right)\cdot\left(p_i^{\left\lfloor\frac{n}{p_i}\right\rfloor}\right)\cdot\left(\left\lfloor\frac{n}{p_i}\right\rfloor\large! \right)$ 上述式子分为三个部分,第一个部分显然在模 $p_i^{k_i}$ 下,是以 $p_i^{k_i}$ 为周期的。可以周期内找循环节算,周期外的暴力算;第二部分可以直接算;第三部分可以递归求解。
另外注意的是求组合逆元的时候,存在阶乘中的某一个数可能还有 $p_i$ 这个质因子,不能直接算。直接把 $p_i$ 全部提出来,最后求完逆元后再补回去。求 $n!$ 内质因子 $p$ 的个数可以用 $\sum\limits_{i=1}^{+\infty} \left\lfloor\frac{n}{p^i}\right\rfloor$ 来求。
1 LL quick_pow(LL a, LL b, LL p) { 2 LL ans = 1; 3 while (b) { 4 if (b&1) ans = ans*a%p; 5 b >>= 1, a = a*a%p; 6 } 7 return ans; 8 } 9 void ex_gcd(LL a, LL b, LL &x, LL &y) { 10 if (b == 0) {x = 1, y = 0; return; } 11 ex_gcd(b, a%b, x, y); 12 LL t = x; x = y, y = t-a/b*y; 13 } 14 LL inv(LL a, LL p) { 15 LL x, y; ex_gcd(a, p, x, y); 16 return (x%p+p)%p; 17 } 18 LL mul(LL n, LL pi, LL pk) { 19 if (!n) return 1; 20 LL ans = 1; 21 for (int i = 2; i <= pk; i++) if (i%pi != 0) ans = ans*i%pk; 22 ans = quick_pow(ans, n/pk, pk); 23 for (int i = 2; i <= n%pk; i++) if (i%pi != 0) ans = ans*i%pk; 24 return ans*mul(n/pi, pi, pk)%pk; 25 } 26 LL C(LL n, LL m, LL pi, LL pk, LL p) { 27 LL a = mul(n, pi, pk), b = mul(m, pi, pk), c = mul(n-m, pi, pk); 28 LL k = 0; 29 for (LL i = n; i; i /= pi) k += i/pi; 30 for (LL i = m; i; i /= pi) k -= i/pi; 31 for (LL i = n-m; i; i /= pi) k -= i/pi; 32 return a*inv(b, pk)%pk*inv(c, pk)%pk*quick_pow(pi, k, pk)%pk; 33 } 34 LL ex_lucas(LL n, LL m, LL p) { 35 LL ans = 0; 36 for (LL i = 2, x = p; i <= x; i++) 37 if (x%i == 0) { 38 LL k = 1; while (x%i == 0) k *= i, x /= i; 39 (ans += C(n, m, i, k, p)*(p/k)%p*inv(p/k, k)%p) %= p; 40 } 41 return ans; 42 }