数学学习笔记2
阶
定义整数 $a$ 如果存在一个正整数 $n$ 满足 $a^n \equiv 1 \pmod m$,那么最小的那个 $n$ 称作整数 $a$ 的阶,记作 $\operatorname{ord}_m(a)$ 或者 $\delta_m(a)$。
容易发现,根据欧拉定理若 $\gcd(a,m)=1$ 那么 $a^{\varphi(m)} \equiv 1 \pmod m$。
性质 1
$a^1,a^2,a^3,\dots,a^{\delta_m(a)}$ 在模 $m$ 意义下两两不同余。
证明
若设 $a^i \equiv a^j \pmod m$,那么 $a_{j-i} \equiv 1 \pmod m$,因为 $1 \le i < j \le \delta_m(a)$,所以 $j-i < \delta_m(a)$,与阶的定义相违背。
性质 2
若 $a^n \equiv 1 \pmod m$ 那么 $\delta_m(a) \mid n$。
证明
若设 $n=p\delta_m(a)+q$,则 $0 \le q < \delta_m(a)$,并且 $a^{p \delta_m(a)} \equiv 1 \pmod m$,所以 $a^q \equiv 1 \pmod m$,如果 $q \ge 1$,与阶的定义相违背,所以 $q=0$,即 $\delta_m(a) \mid n$。
推论
若 $a^p \equiv a^q \pmod m$,那么 $p \equiv q \pmod {\delta_m(a)}$。
性质 3
若 $m \in N^*$,$a,b \in Z$,$\gcd(a,m)=\gcd(b,m)=1$,则:
$$
\delta_m(a)\delta_m(b)=\delta_m(ab)
$$
的充要条件是 $\gcd(\delta_m(a),\delta_m(b))=1$。
证明
必要性
因为 $a^{\delta_m(a)} \equiv 1$,$b^{\delta_m(b)} \equiv 1$,所以 $(ab)^{[\delta_m(a),\delta_m(b)]} \equiv 1$。
那么根据性质 $2$ 可得 $\delta_m(ab) \mid [\delta_m(a),\delta_m(b)]$,所以 $\delta_m(a)\delta_m(b) \mid [\delta_m(a),\delta_m(b)]$,推出 $(\delta_m(a),\delta_m(b))=1$。
充分性
由 $(ab)^{\delta_m(ab)} \equiv 1$,那么 $(ab)^{\delta_m(ab)\delta_m(b)} \equiv a^{\delta_m(ab)\delta_m(b)}\equiv 1$。
所以 $\delta_m(a)\mid \delta_m(ab)\delta_m(b)$,因为 $\gcd(\delta_m(a),\delta_m(b))=1$,所以 $\delta_m(a) \mid \delta_m(ab)$。
对称地,那么 $\delta_m(b) \mid \delta_m(ab)$。
所以 $\delta_m(a)\delta_m(b) \mid \delta_m(ab)$。
另一方面有:$(ab)^{\delta_m(a)\delta_m(b)}\equiv (a^{\delta_m(a)})^{\delta_m(b)} (b^{\delta_m(b)})^{\delta_m(a)} \equiv 1$。
所以 $\delta_m(ab) \mid \delta_m(a)\delta_m(b)$。
综上所述,有 $\delta_m(a)\delta_m(b)=\delta_m(ab)$。
性质 4
对于合法的 $a,k,m$,有 $\delta_m(a^k)=\dfrac{\delta_m(a)}{\gcd(\delta_m(a),k)}$。
证明
首先有 $a^{k\delta_m(a^k)} \equiv (a^k)^{\delta_m(a^k)} \equiv 1$,所以 $\delta_m(a) \mid k\delta_m(a^k)$,推得 $\dfrac{\delta_m(a)}{\gcd(\delta_m(a),k)} \mid \delta_m(a^k)$。
还有 $a^{\delta_m(a)} \equiv 1$,可得 $(a^k)^{\frac{\delta_m(a)}{\gcd(\delta_m(a),k)}} \equiv (a^{\delta_m(a)})^{\frac{k}{\gcd(k,\delta_m(a))}} \equiv 1$。
所以 $\delta_m(a^k) \mid \dfrac{\delta_m(a)}{\gcd(\delta_m(a),k)}$,综上所述,$\delta_m(a^k) = \dfrac{\delta_m(a)}{\gcd(\delta_m(a),k)}$。
阶的寻找
如果 $\gcd(a,m) \not=1$ 的话,说明 $a^k \not\equiv 1 \pmod m$,可以用 $a \equiv b \pmod m$ 与 $\dfrac{a}{\gcd(a,m)} \equiv \dfrac{b}{\gcd(a,m)} \pmod {\dfrac{m}{\gcd(a,m)}}$ 等价证明。
所以当 $\gcd(a,m)=1$ 时 $a$ 才有阶,此时 $a^{\varphi(m)} \equiv 1$,根据欧拉定理及其推论可以得 $\delta_m(a) \mid \varphi(m)$。
于是我们对于 $\varphi(m)$ 分解质因数,然后依次除以每个质因数,再用快速幂判断是不是为 $1$ 就可以了,如果为 $1$ 就除一下,否则继续试除即可。
寻找阶的代码(没有用试除优化):
1 |
|
原根
定义
对于合法的 $g,m$,如果其满足 $\delta_m(g) = \varphi(m)$,那么则称 $g$ 是模 $m$ 的原根。
容易发现,当 $m$ 为质数时对于任意 $0<i<m$ 的 $g_i \bmod m$ 互不相同。
判定
若 $g$ 是模 $m$ 的原根,首先满足 $\gcd(g,m)=1$(欧拉定理),然后对于 $m$ 的每个质因数 $t$ 都要满足 $g^{\frac{m}{t}} \not\equiv 1$。
证明显然,此处不展开叙述。
个数
如果一个数 $m$ 有原根,那么它的个数是 $\varphi(\varphi(m))$。
证明
设 $g$ 是 $m$ 的任意一个原根,则有:
$$
\delta_m(g^k)=\dfrac{\delta_m(g)}{\gcd(\delta_m(g),k)}
$$
所以当 $\gcd(\delta_m(g),k)=1$ 时,$\delta_m(g^k)=\varphi(m)$,因为 $\delta_m(g)=\varphi(m)$,所以个数是 $\varphi(\varphi(m))$。
原根存在定理
一个数 $m$ 存在原根当且仅当它等于 $2$ 或 $4$ 或 $p^k$ 或 $2p^k$。
证明略。
最小原根范围
可证 $g$ 大概在 $m^{\frac{1}{4}}$ 左右,所以暴力找原根的时间复杂度是可以接受的。
寻找原根的代码:
1 |
|
BSGS 算法
定义
已知 $a,b,p$,求最小的 $t$ 满足下列公式:
$$
a^t \equiv b \pmod{p}
$$
普通的 BSGS 算法能够在 $\gcd(a,p)$ 互质时以 $O(\sqrt{p})$ 的时间复杂度内得出答案。
解决
核心思想是根号分治。
设 $r = \lceil{\sqrt{t}}\rceil$,则 $t=rk+q(0 \leq q < r)$。
写到式子上就是:
$$
a^{rk+q} \equiv b \pmod{p}
$$
因为 $a$ 有模 $p$ 意义下的逆元,我们可以将式子转化为下面的形式:
$$
a^{rk} \equiv b \times a^{-q} \pmod{p}
$$
注意到左边有不超过根号种取值,右边也有不超过根号种取值,于是预处理两边中的任意一边即可,剩下的那边暴力枚举就好。
时间复杂度看你存储一边的时候使用的数据结构,如果是 $\text{map}$,时间复杂度多一个 $\log$;如果是 $\text{unordered_map}$,时间复杂度多一个常数。(模运算具有较大的随机性)
除此之外,我们也可以写成 $a^t=a^{kr-q}$ 的形式,代码就是采用的这种结构,但是边界情况一定要判断好。
1 |
|
广义 BSGS
如果定义一种运算 $p \times q = k$,并且对于 $a$ 存在某个结构 $a^{-1}$ 使得 $a \times a^{-1}=e$,$e$ 是这种运算的单位元,那么都可以采用 BSGS 求解。
比如矩阵就可以采用 BSGS 求解,即把上述运算全部改成矩阵的乘法、快速幂即可,时间复杂度为 $O(\sqrt{p}) \times k$,$k$ 是执行一次我们定义的运算的时间复杂度。
Millar-Rabin
判定素数经常被认为是一个 NP 问题,但是实际上有确定性多项式算法解决这个问题,但是它在算法竞赛中并不常用,而 Millar-Rabin 是一个非确定性的算法来解决素数判定问题。
时间复杂度为执行判定的次数乘上 $\log n$。
理论
有费马小定理当 $p$ 是质数的时候 $a^{p-1} \equiv 1 \pmod p(1 \le a < p)$,但是反过来是否如此呢?
事实上反过来会有一种数满足它仍然成立但是不是质数($a$ 不整除它),这种数称作 Carmichael 数,例如 $561=3 \times 11 \times 17$ 就是 Carmichael 数。
Carmichael 数一定有超过三个不同的质因子,并且不包含平方因子。
于是根据这点,我们得到了一个最简单的判定方法,称作 Fermat 素性测试,代码如下:
1 | bool millerRabin(int n) { |
但是我们这个测试无法确定 Carmichael 数的素性,于是我们引进了二次探测定理。
若 $p$ 是质数,则满足 $x^2 \equiv 1 \pmod p$ 的 $x$ 只可能等于 $1$ 或 $p-1$。
我们可以分解一下 $(x-1)(x+1) \equiv 0 \pmod p$,因为 $p$ 是质数,所以 $x-1$ 或者 $x+1$ 等于 $p$。
那么也有数可以通过二次探测定理的逆命题,但是这些数一定是 $p^k$,与 Carmichael 没有交集,故我们可以根据这两个定理设计素数判定的方案。
处理
将 $a^{n-1} \equiv 1 \pmod n$ 中的指数 $n-1$ 分解为 $n-1=u \times 2^t$,在每轮测试中对随机出来的 $a$ 先求出 $v = a^{u} \bmod n$,之后对这个值执行最多 $t$ 次平方操作,若发现非平凡平方根时即可判断出其不是素数,否则再使用 Fermat 素性测试判断。
有一个问题,就是如果 $v$ 在进入循环之前就等于 $1$ 了,那就直接跳过即可,如果 $t$ 次平方操作之后结果仍然不为 $1$(数字不为 $n-1$),那就返回不是素数即可。
代码如下:
1 | inline bool check(ll x){ |
选择的数字看判断素数的范围,如果是 int
类型,那么取判定的底数 $a=2,7,61$ 即可;否则取 $a$ 为前 $12$ 个质数即可。
Pollard-Rho
给定一个正整数 $N \in \mathbf{N}_{+}$,试快速找到它的一个非平凡因数。
首先,有一个悖论称作“生日悖论”,如果一年有 $365$ 天,那么一个班如果有至少 $23$ 个人,那么有两个人生日相同的概率将达到 $50%$,如果有至少 $56$ 个人,概率近乎 $100%$。
我们还可以通过最大公因数来找出某个数的非平凡因子,即如果 $\gcd(k,n)>1$,那么 $\gcd(k,n)$ 一定是大于 $1$ 的 $n$ 的因子。
我们考虑一个启发式伪随机 $f(x)=(x^2+c)\bmod n$ 来生成一个序列 $x_i$:随机取一个 $x_1$,令 $x_2=f(x_1),x_3=f(x_2),\cdots,x_i=f(x_{i-1})$。其中 $c$ 是一个随机选取的常数。
因为这个序列生成的数列是一个 rho 形态的,就是一个环上面掉了一个链,所以成为 Pollard-Rho。
这个函数生成序列还有一个性质,如果 $x \equiv y \pmod p$,那么 $f(x) \equiv f(y) \pmod p$。
证明显然。
那么根据生日悖论,我们可以在这个环上任取两个数使得这两个数的差的 $n$ 的最大公因数大于 $1$,我们就可以找出来一个因数,这样的时间复杂度就是 $O(n^{\frac{1}{4}})$。
我们就可以设置两个指针,一个走慢一点,一个走快一点,大概是一倍的速度差,然后判断这两个指针的差值即可。
同时因为 $\gcd(a,n)>1$,那么 $\gcd(ac,n)>1$,我们可以通过倍增计算,即每隔 $2^k-1$ 个数,计算两个指针的差值,如果两个指针相等了,那么说明它们处在同一个位置,重新执行即可。
1 | inline ll pollard_rho(ll x){ |
总的时间复杂度是小常 $\log$ 乘上 $n^{\frac{1}{4}}$。
MIN_25 筛
基础算法
给定 $n$,求 $\pi(n)$,$n \le 10^{11}$。
我们考虑埃氏筛法,那么每一轮枚举 $1 \sim n$ 的质数,但是事实上只需要枚举 $1 \le \sqrt{n}$ 的质数就可以了,因为一个数是合数的话其最小质因子 $\le \sqrt{n}$。
所以对于每一轮枚举完之后剩下没有被标记的数有 $g(n,k)$ 个,$n$ 是值域,$k$ 是枚举完的轮数,设 $p_k$ 是从小到大第 $k$ 个质数,则有下面的公式:
$$
g(n,k)=g(n,k-1)-g(\lfloor \dfrac{n}{p_k} \rfloor,k-1)+k-1
$$
考虑意义,首先我们考虑 $k$ 这一轮筛掉了多少数字,设它们分别为 $a_1,a_2,a_3,\dots,a_m$,那么它们的最小质因子等于 $p_k$,则让它们除以 $p_k$ 之后得到 $\dfrac{a_1}{p_k},\dfrac{a_2}{p_k},\dfrac{a_3}{p_k},\dots,\dfrac{a_m}{p_k}$,这个时候它们的最小质因子大于等于 $p_k$,则这些数的个数是 $g(\lfloor \dfrac{n}{p_k} \rfloor,k-1)-(k-1)$,为什么要减 $k-1$ 呢,是因为这一坨同时算上了质数 $2,3,5,7,\dots$,为了去除多算的,就要减去 $k$ 之前的质数个数 $k-1$ 个。
代码如下:
1 |
|
时间复杂度证明此处就不说了,但是总的时间复杂度大概是 $O(\dfrac{n^{\frac{3}{4}}}{\ln n})$。
特别的,如果是求 $1 \sim n$ 中质数的和,把公式改为下面即可(其实就是动态规划):
$$
f(n,k)=f(n,k-1)-p_k \times f(\lfloor \dfrac{n}{p_k} \rfloor,k-1)+\sum_{i=1}^{k-1} p_i \times p_k
$$