5401 字
27 分钟
基础数论复习

数论,是一门研究整数的纯数学的分支,而整数的基本元素是素数(也称质数),所以数论的本质是对素数性质的研究。

素数#

一些基本概念就不写了.

注意两点:

  1. 0、1、负整数既不是素数也不是合数.
  2. π(n)\pi(n) 表示不大于 nn 的素数个数, 有如下近似关系 π(n)∼nln⁡n\pi(n)\sim\dfrac{n}{\ln{n}} .

素数判定#

如何判定正整数 nn 是否是素数?

很容易想到用每一个小于 nn 且大于 11 的数来判断它是否是 nn 的约数, 若都不是, 则 nn 为素数, 否则为合数.

这个暴力算法是 O(n)\mathcal{O}(n) 的, 但是我们考虑到, 若数 pp 为 nn 的约数, 则 np\frac{n}{p} 也是 nn 的约数, 所以我们只需用 2∼n2\sim \sqrt{n} 的数来判定即可, 于是优化一下我们得到一个 O(n)\mathcal{O}(\sqrt{n}) 的算法.

bool isPrime(int n) {
if (n == 1) return false;
if (n == 2) return true;
for (int i = 2; i * i <= n; ++i)
if (n % i == 0) return false;
return true;
}

整数惟一分解定理#

若整数 n≥2n\ge2 , 那么 nn 一定可以惟一地表示为若干素数的乘积, 形如

n=p1r1p2r2⋯pkrk(pi为素数,ri≥0)n=p_1^{r_1}p_2^{r_2}\cdots p_k^{r_k}(p_i为素数, r_i\ge0)

vector <int> factor(int n) {
vector <int> ret;
for (int i = 2; i * i <= n; ++i)
while (n % i == 0) {
ret.push_back(i);
n /= i;
}
if (n > 1) ret.push_back(n);
return ret;
}

素数筛法#

主要是埃氏筛法和欧拉筛法.

Eratosthenes 筛法#

Eratosthenes 筛法可以快速列举出给定范围内的所有素数.

一个合数一定可以写成 p⋅xp\cdot x 的形式, 其中 pp 为素数, xx 为整数, 因此对每一个 pp , 我们从小到大枚举 xx , 筛掉相应的 p⋅xp\cdot x 即可.

一点小改进: 当 x<px<p 时, p⋅xp\cdot x 一定被 xx 的素因子筛过一遍, 所以我们枚举 xx 时从 x=px=p 开始枚举.

时间复杂度: O(n2+n3+n5+⋯ )=O(nlog⁡log⁡n)\mathcal{O}(\frac{n}{2}+\frac{n}{3}+\frac{n}{5}+\cdots)=\mathcal{O}(n\log{\log{n}})

bool isprime[N];
void Eratos(int n) {
memset(isprime, 1, sizeof isprime);
isprime[0] = isprime[1] = 0;
for (int i = 2; i * i <= n; ++i)
if (isprime[i]) {
for (int j = i * i; j <= n; j += i)
isprime[j] = 0;
}
}

例题#

「POJ 2689」Prime Distance

由于这里 L,RL,R 的范围很大, 暴力筛完之后枚举求解肯定会 T , 但是 R−L≤106R-L\le 10^6 的范围却是在我们的承受范围之内的.

于是我们考虑用 1∼n1\sim n 这一小范围的素数筛掉 L∼RL\sim R 之间的合数.

假设数 k∈[L,R]k\in[L, R] , 其中 kk 的最小质因数为 pp , 满足 p>np>n , 则 k=p⋅xk=p\cdot x , 若 x<px<p , 则 kk 一定存在小于 pp 的质因数, 矛盾, 故而 x≥px\ge p , 也就是说, 会被漏筛的数 kk 满足 k≥p2k\ge p^2 , 为了保证算法的正确性, 我们要让这样的数落在 [L,R][L, R] 外, 也就是让 p2>Rp^2>R , 于是我们令 n=Rn=\sqrt{R} 即可.

筛法优化质因数分解#

利用埃氏筛法可以快速实现素因数分解, 只要在筛的时候记录下每个数的最小素因数即可.

bool isprime[N];
int minfac[N];
void Eratos(int n) {
memset(isprime, 1, sizeof isprime);
isprime[0] = isprime[1] = 0;
for (int i = 1; i <= n; ++i) minfac[i] = i;
for (int i = 2; i * i <= n; ++i)
if (isprime[i]) {
for (int j = i * i; j <= n; j += i) {
isprime[j] = 0;
if (minfac[j] == j) minfac[j] = i;
}
}
}
vector <int> factor(int n) {
vector <int> ret;
while (n > 1) {
ret.push_back(minfac[n]);
n /= minfac[n];
}
return ret;
}

Euler 筛法#

在埃氏筛中, 30 这个数被 p=2,3,5p=2,3,5 分别筛了三次, 造成了重复, 如果我们能让每个数只被它最小的素因数筛, 就能做到 O(n)\mathcal{O}(n) 的时间复杂度.

在 Euler 筛法中, 我们从 2∼n2\sim n 枚举每一个数 ii , 若 ii 是素数, 则加入素数表中, 然后我们再从小到大枚举前面的素数 prime[j]prime[j] , 筛掉 i⋅prime[j]i\cdot prime[j] , 当 prime[j]prime[j] 是 ii 的一个素因数时, 那么后面再继续枚举到的素数一定不是所筛的数的最小素因数, 毕竟后面的素数一定大于当前的 prime[j]prime[j] , 所以这时可以终止筛选.

时间复杂度: O(n)\mathcal{O}(n)

int prime[N];
bool isprime[N];
void Euler(int n) {
memset(isprime, 1, sizeof isprime);
isprime[0] = isprime[1] = 0;
for (int i = 2; i <= n; ++i) {
if (isprime[i]) prime[++prime[0]] = i;
for (int j = 1; j <= prime[0] && prime[j] * i <= n; ++j) {
isprime[i * prime[j]] = 0;
if (i % prime[j] == 0) break;
}
}
}

约数#

整数惟一分解定理的推论#

N=p1r1p2r2⋯pkrkN=p_1^{r_1}p_2^{r_2}\cdots p_k^{r_k}

  1. NN 的正约数的个数为 (r1+1)(r2+1)⋯(rk+1)=∏i=1k(ri+1)(r_1+1)(r_2+1)\cdots(r_k+1)=\prod_{i=1}^k(r_i+1)
  2. NN 的约数个数上界为 N\sqrt{N}
  3. NN 的所有正约数的和为 (1+p1+p12+⋯+p1r1)⋯(1+pk+⋯+pkrk)=∏i=1k(∑j=0ripij)(1+p_1+p_1^2+\cdots+p_1^{r_1})\cdots(1+p_k+\cdots+p_k^{r_k})=\prod_{i=1}^k(\sum_{j=0}^{r_i}p_i^j)
  4. 时间复杂度: O(N)\mathcal{O}(\sqrt{N})

例题#

「Luoggu P1463」反素数

这道题只需要知道 1∼2⋅1091\sim 2\cdot 10^9 内前 12 个素数的积就已经超出 NN 的范围, 所以打个表然后直接爆搜即可.

(亏我想了半天要怎么转化, 完全没考虑只有 12 个素数会被用到)

最大公约数#

左转 gcd & lcm 复习笔记

高精度 gcd⁡(a,b)\gcd{(a, b)}#

更相减损术适用于大整数下求 gcd⁡(a,b)\gcd(a, b)

  1. a<ba<b 时, gcd⁡(a,b)=gcd⁡(b,a)\gcd(a, b)=\gcd(b, a)
  2. a=ba=b 时, gcd⁡(a,b)=a\gcd(a, b)=a
  3. a,ba, b 同为偶数时, gcd⁡(a,b)=2gcd⁡(a2,b2)\gcd(a, b)=2\gcd(\frac{a}{2}, \frac{b}{2})
  4. aa 为偶数, bb 为奇数时, gcd⁡(a,b)=gcd⁡(a2,b)\gcd(a, b)=\gcd(\frac{a}{2}, b)
  5. aa 为奇数, bb 为偶数时, gcd⁡(a,b)=gcd⁡(a,b2)\gcd(a, b)=\gcd(a, \frac{b}{2})
  6. a,ba, b 同为奇数时, gcd⁡(a,b)=gcd⁡(b,a−b)\gcd(a, b)=\gcd(b, a-b)

容斥原理#

原理很简单, 记住一个公式即可

∣∩Ai∣=∑1≤i≤m∣Ai∣−∑1≤i<j≤m∣Ai∩Aj∣+∑1≤i<j<k≤m∣Ai∩Aj∩Ak∣−⋯+(−1)m+1∑∣A1∩A2∩⋯∩Am∣|\cap A_i|=\sum_{1\le i\le m}|A_i|-\sum_{1\le i< j\le m}|A_i\cap A_j|+\sum_{1\le i<j<k\le m}|A_i\cap A_j\cap A_k|-\cdots+(-1)^{m+1}\sum|A_1\cap A_2\cap\cdots\cap A_m|

错排问题#

  1. 利用容斥原理求解

    令集合 SS 表示 1,2,⋯ ,n1,2, \cdots, n 的全排列, 则 ∣S∣=n!|S|=n!

    设子集 SiS_i 表示 ii 排在第 ii 位的排列, 则 ∣Si∣=(n−1)!|S_i|=(n-1)!

    同理, 设 Si1∩Si2∩⋯∩SikS_{i_1}\cap S_{i_2}\cap\cdots\cap S_{i_k} 表示 i1,i2,⋯ ,iki_1, i_2, \cdots, i_k 这 kk 个数排在相应位置的排列数, 则 ∣Si1∩Si2∩⋯∩Sik∣=(n−k)!|S_{i_1}\cap S_{i_2}\cap\cdots\cap S_{i_k}|=(n-k)!

    每个元素都不排在自己位置的排列数为 Dn=∣S1‾∩S2‾∩⋯∩Sn‾∣=∣S∣−∣S1∪S2∪⋯∪Sn∣D_n=|\overline{S_1}\cap\overline{S_2}\cap\cdots\cap\overline{S_n}|=|S|-|S_1\cup S_2\cup\cdots\cup S_n|

    由容斥原理可得

    Dn=n!(1−11!+12!−13!+⋯±1n!)D_n=n!(1-\frac{1}{1!}+\frac{1}{2!}-\frac{1}{3!}+\cdots\pm\frac{1}{n!})

  2. 递推公式

    推导过程并不难想, 懒得写了, 直接上公式

    Dn=(n−1)(Dn−1+Dn−2)D_n=(n-1)(D_{n-1}+D_{n-2})

欧拉函数#

  1. 若 gcd⁡(a,b)=1\gcd{(a, b)}=1 , 则称 a,ba, b 互质(互素), 记作 a⊥ba\bot b
  2. 欧拉函数 φ(n)\varphi(n) 定义为 [1,n][1, n] 中与 nn 互质的数的个数.
  3. 若 nn 为素数, 则 φ(n)=n−1\varphi(n)=n-1

容斥原理求欧拉函数#

根据整数惟一分解定理, 将 NN 分解为

N=p1r1p2r2⋯pkrkN=p_1^{r_1}p_2^{r_2}\cdots p_k^{r_k}

设 [1,n][1, n] 中 pip_i 的倍数的集合为 AiA_i , 则 ∣Ai∣=⌊Npi⌋|A_i|=\lfloor \frac{N}{p_i}\rfloor

对于 pi≠pjp_i\not=p_j , 有 ∣Ai∩Aj∣=⌊Npipj⌋|A_i\cap A_j|=\lfloor\frac{N}{p_ip_j}\rfloor

根据容斥原理,

φ(N)=∣A∣−∣A1‾∪A2‾∪⋯∪Ak‾∣ =N−(Np1+Np2+⋯+Npk)+(Np1p2+⋯+Np1pk)−⋯±Np1p2⋯pk =N(1−1p1)(1−1p2)⋯(1−1pk)\begin{aligned}\varphi(N)&=|A|-|\overline{A_1}\cup\overline{A_2}\cup\cdots\cup\overline{A_k}| \\\ &=N-(\frac{N}{p_1}+\frac{N}{p_2}+\cdots+\frac{N}{p_k})+(\frac{N}{p_1p_2}+\cdots+\frac{N}{p_1p_k})-\cdots\pm\frac{N}{p_1p_2\cdots p_k} \\\ &=N(1-\frac{1}{p_1})(1-\frac{1}{p_2})\cdots(1-\frac{1}{p_k})\end{aligned}

素因数分解求欧拉函数的算法#

时间复杂度: O(n)\mathcal{O}(\sqrt{n})

int euler_phi(int n) {
int ret = n;
for (int i = 2; i * i <= n; ++i)
if (n % i == 0) {
ret = ret / i * (i - 1);//先除后乘可以一定程度上避免爆 int
while (n % i == 0) n /= i;
}
if (n > 1) ret = ret / n * (n - 1);
return ret;
}

埃氏筛法预处理欧拉函数值#

时间复杂度: O(nlog⁡log⁡n)\mathcal{O}(n\log{\log{n}})

int phi[N];
void euler_phi(int n) {
for (int i = 2; i <= n; ++i) phi[i] = i;
for (int i = 2; i * i <= n; ++i)
if (phi[i] == i) {
phi[i] = i - 1;
for (int j = i; j <= n; j += i)//注意这里 j 的起点是 i 而不是 i * i
phi[j] = phi[j] / i * (i - 1);
}
}

欧拉函数的性质#

若 a⊥ba\bot b , 则 φ(a)φ(b)=φ(ab)\varphi(a)\varphi(b)=\varphi(ab) , 即欧拉函数具有积性函数的性质.

上式分别将 a,ba, b 用整数惟一分解定理表示, 然后带入欧拉函数计算式即可得到证明.

例题#

「POJ 3090」Visible Lattice Points

设某点坐标为 (x0,y0)(x_0, y_0) , 若该点能被看见, 则这个点一定是直线 y=y0x0xy=\frac{y_0}{x_0}x 上距离原点最近的一个整数点.

我们设一点 (x1,y1)(x_1, y_1) 满足 y1x1=y0x0,x1>x0\frac{y_1}{x_1}=\frac{y_0}{x_0}, x_1>x_0 , 则该点显然不可见, 从这个式子中我们可以知道, x1,y1x_1, y_1 必然存在一个公约数, 而 x0,y0x_0, y_0 不存在公约数, 即 x0,y0x_0, y_0 互质, 因此可见点就是图中所有满足 x0,y0x_0, y_0 互质的点再加上 (1,0),(0,1),(1,1)(1, 0), (0, 1), (1, 1) .

固定 y=y0y=y_0 , 当 x<y0x<y_0 时, 满足条件的点的数量就是 φ(y0)\varphi(y_0) , 当 x>y0x>y_0 时, 将点 (x,y0)(x, y_0) 以 y=xy=x 对称过去得到的点就是固定 x=xix=x_i 时 y<xiy<x_i 的情况, 根据坐标轴关于 y=xy=x 对称的性质, x<y0x<y_0 和 x>y0x>y_0 两种情况下的答案数相等, 所以我们只需考虑 x<y0x<y_0 的情况, 然后乘 2 即可.

最终的答案为: 3+2⋅∑i=2Nφ(i)3+2\cdot\sum_{i=2}^N \varphi(i)

「Luogu P2303」Longge 的问题

考虑满足 gcd⁡(i,n)=d\gcd(i, n)=d 的 ii 的个数.

由 gcd⁡(i,n)=d\gcd(i, n)=d 可以推出 gcd⁡(id,nd)=1\gcd(\frac{i}{d}, \frac{n}{d})=1, 即 id,nd\frac{i}{d}, \frac{n}{d} 互质, 又 id<nd\frac{i}{d}<\frac{n}{d} , 所以这样的 id\frac{i}{d} 的个数为 φ(nd)\varphi(\frac{n}{d}) , 也就是 ii 的个数为 φ(nd)\varphi(\frac{n}{d})

所以答案为 ∑d∣ndφ(nd)\sum_{d|n}d\varphi(\frac{n}{d})

同余#

剩余系#

  1. 剩余系指模正整数 nn 的余数所组成的集合.
  2. 完全剩余系: 如果一个剩余系中包含了这个正整数 nn 所有可能的余数 (0,1,⋯ ,n−10, 1, \cdots, n-1) , 那么就称它为模 nn 的一个完全剩余系, 记作 ZnZ_n . 简化剩余系:完全剩余系中与 nn 互质的数的集合, 记作 Zn∗Z_n^* .
  3. 同余等价类: ZnZ_n 里的每一个元素代表所有模 nn 意义下与它同余的整数, 我们把满足同余关系的所有整数看作一个同余等价类.
  4. 在 ZnZ_n 中的四则运算结果全部都要在模 nn 意义下.

模运算#

  1. 如果 a≡b(modm)a\equiv b\pmod{m} 且有 c≡d(modm)c\equiv d\pmod{m} , 那么:

    a+c≡b+d(modm)a+c\equiv b+d\pmod{m}

    a−c≡b−d(modm)a-c\equiv b-d\pmod{m}

    a×c≡b×d(modm)a\times c\equiv b\times d\pmod{m}

  2. (a+b) mod m=((a mod m)+(b mod m)) mod m(a+b)\bmod m=((a\bmod m)+(b\bmod m))\bmod m

    (a−b) mod m=((a mod m)−(b mod m)+m) mod m(a-b)\bmod m=((a\bmod m)-(b\bmod m)+m)\bmod m

    (a×b) mod m=((a mod m)×(b mod m)) mod m(a\times b)\bmod m=((a\bmod m)\times(b\bmod m))\bmod m

快速幂#

右转 快速幂复习笔记

费马小定理#

若 pp 为素数, 且 a⊥pa\bot p , 则 ap−1≡1(modp)a^{p-1}\equiv 1\pmod{p} .

因为 pp 为素数, 则 2,3,⋯ ,p−12, 3, \cdots, p-1 与 pp 互质, 且不存在两个数模 pp 同余.

又 a⊥pa\bot p , 所以 a,2a,3a,⋯ ,(p−1)aa, 2a, 3a, \cdots, (p-1)a 与 pp 互质, 且不存在两个数模 pp 同余.

因此 a⋅2a⋅3a⋯(p−1)a=(p−1)!ap−1a\cdot 2a\cdot 3a\cdots(p-1)a=(p-1)!a^{p-1} 与 pp 互质, 且 (p−1)!ap−1≡(p−1)!(modp)(p-1)!a^{p-1}\equiv (p-1)!\pmod{p}

两边同时除以 (p−1)!(p-1)! 得到 ap−1≡1(modp)a^{p-1}\equiv 1\pmod{p}

  1. 费马小定理的另一种形式: 若 pp 为素数, 则对任意正整数 aa 有 ap≡a(modp)a^p\equiv a\pmod{p}.
  2. 应用: pp 是素数, a,pa, p 互质, 则 ab mod p=ab mod (p−1) mod pa^b\bmod{p}= a^{b\bmod (p-1)}\bmod{p} .

费马小定理判断素数#

  1. 多次选取 aa 来判断 pp 是否满足费马小定理, 正确的概率随 aa 选取的次数的增加而增加.
  2. 时间复杂度: 设选取 kk 次 aa , 每次用快速幂处理的时间为 O(log⁡p)\mathcal{O}(\log{p}) , 则总时间复杂度为 O(klog⁡p)\mathcal{O}(k\log{p}) .
  3. 由于存在 Carmichael 数, 因此上述算法存在缺陷, 即存在合数满足费马小定理.
  4. 10410^4 以内的 Carmichael 数有: 561, 1105, 1729, 2465, 2821, 6601, 8911.

欧拉定理#

(在 pp 不是素数的情况下, 可以使用欧拉定理)

对于和 mm 互素的 aa , 有: aφ(m)≡1(modm)a^{\varphi(m)}\equiv1\pmod{m} .

证明方法和费马小定理差不多.

引理: 若 a,ma, m 互质, 满足 ax≡1(modm)a^x\equiv 1\pmod{m} 的最小正整数 x0x_0 是 φ(m)\varphi(m) 的约数.

欧拉定理的推论#

a,m(m>1)a, m(m>1) 互素, 则有 ab mod m=ab mod φ(m) mod ma^b\bmod{m}=a^{b\bmod\varphi(m)}\bmod m .

例题#

「POJ 3696」The Luckiest number

设 nn 个 8 连在一起的正整数为 AnA_n , 则 An=10An−1+8A_n=10A_{n-1}+8 , 容易求得 An=89(10n−1)A_n=\frac{8}{9}(10^n-1) .

若 L∣AnL|A_n , 即 L∣89(10n−1)L|\frac{8}{9}(10^n-1), 可以得到 9L∣8(10n−1)9L|8(10^n-1) , 令 d=gcd⁡(9L,8)d=\gcd(9L, 8) , 则有 9Ld∣(10n−1)\frac{9L}{d}|(10^n-1)

于是 10n≡1(mod9Ld)10^n\equiv 1\pmod{\frac{9L}{d}}

根据欧拉定理的引理, 只需求出 φ(9Ld)\varphi(\frac{9L}{d}) , 然后枚举它的约数, 一一验证后取最小的一个数即可.

时间复杂度: O(Llog⁡L)\mathcal{O}(\sqrt{L}\log{L})

扩展欧几里得算法#

裴蜀定理 ( Bézout 定理 )#

对任何整数 a,ba, b , 关于未知数 x,yx, y 的线性不定方程 ( 称为裴蜀等式 ) ax+by=cax+by=c 有整数解当且仅当 cc 为 gcd⁡(a,b)\gcd{(a, b)} 的倍数.

裴蜀等式有解时必有无穷多个解.

推论: a,ba, b 互素等价于 ax+by=1ax+by=1 有整数解.

例题#

「BZOJ 1441」Min

假设 SS 已知, 于是有方程 A1x1+A2x2+⋯+Anxn=SA_1x_1+A_2x_2+\cdots+A_nx_n=S

根据裴蜀定理, SS 必然是 gcd⁡(A1,A2,⋯ ,An)\gcd{(A_1, A_2, \cdots, A_n)} 的倍数, 取 Smin=gcd⁡(A1,A2,⋯ ,An)S_{min}=\gcd{(A_1, A_2, \cdots, A_n)} 即可.

扩展欧几里得算法#

见 gcd & lcm 复习笔记

根据裴蜀定理, ax+by=gcd⁡(a,b)ax+by=\gcd{(a, b)} 有无穷组解, 而扩展欧几里得算法求出来的只是其中一组特解 (x0,y0)(x_0, y_0) .

下面考虑求 ax+by=cax+by=c 的一般解.

首先设 c=tgcd⁡(a,b)c=t\gcd(a, b) ( tt 为整数 ) , 则使用扩展欧几里得算法求出 ax+by=gcd⁡(a,b)ax+by=\gcd{(a, b)} 的特解 (x0,y0)(x_0, y_0) 后, 容易得到 ax+by=cax+by=c 特解为 (tx0,ty0)(tx_0, ty_0) .

由于之后考虑的是 ax+by=cax+by=c , 所以后面用 (x0,y0)(x_0, y_0) 代替 (tx0,ty0)(tx_0, ty_0) .

将方程的所有解按照 xx 的大小排序, 则特解后的下一组解 (x1,y1)(x_1, y_1) 可以表示为 (x0+d1,y0+d2)(x_0+d_1, y_0+d_2) , 其中 d1d_1 为满足条件的最小正整数.

带入方程后得到 ad1+bd2=0ad_1+bd_2=0 , 变形后有 −d1d2=ba=bgcd⁡(a,b)agcd⁡(a,b)-\dfrac{d_1}{d_2}=\dfrac{b}{a}=\dfrac{\frac{b}{\gcd{(a, b)}}}{\frac{a}{\gcd{(a, b)}}} .

因此方程的一般解可以表示为 (x0+kbgcd⁡(a,b),y0−kagcd⁡(a,b))(k∈Z)\left(x_0+k\dfrac{b}{\gcd{(a, b)}}, y_0-k\dfrac{a}{\gcd{(a, b)}}\right)(k\in \mathbf{Z}) .

为什么这里要将 ba\dfrac{b}{a} 再变形为 bgcd⁡(a,b)agcd⁡(a,b)\dfrac{\frac{b}{\gcd{(a, b)}}}{\frac{a}{\gcd{(a, b)}}} 呢?

因为 ba\frac{b}{a} 不是最简分数, 这一步变形是化简 ba\frac{b}{a} , 直接用 (x0+kb,y0−ka)(x_0+kb, y_0-ka) 来表示特解的话会漏掉一些情况, 如 (x0+bgcd⁡(a,b),y0−agcd⁡(a,b))(x_0+\frac{b}{\gcd{(a, b)}}, y_0-\frac{a}{\gcd{(a, b)}}) 就不能被 (x0+kb,y0−ka)(x_0+kb, y_0-ka) 表示.

逆元#

模 nn 意义下乘法的逆#

如果在 ZnZ_n 中两元素 a,ba, b 满足 a⋅b=1a\cdot b=1 , 那么我们就说 a,ba, b 互为模 nn 意义下乘法的逆元, 记作 a=b−1,b=a−1a=b^{-1}, b=a^{-1} .

逆元#

当 a,ma, m 互素的时候, 若 ax≡1(modm)ax\equiv 1\pmod{m} , 则称 xx 为 aa 关于模 mm 的逆元, 记作 a−1a^{-1} .

在 [0,m)[0, m) 的范围内, 逆元是唯一的.

求解逆元#

求解逆元等价于解方程 ax+my=1ax+my=1

直接使用扩展欧几里得算法即可.

欧拉定理求逆元#

因为 a,ma, m 互素, 根据欧拉定理, 有 a⋅aφ(m)−1≡1(modm)a\cdot a^{\varphi(m)-1}\equiv 1\pmod{m} , 因此 aφ(m)−1a^{\varphi(m)-1} 为所求逆元.

线性求逆元: 递推法#

递推法求解 1∼n1\sim n 的逆元.

假设当前求解的是 ii 关于模 pp 的逆元.

根据带余除法, p=iq+rp=iq+r , 两边分别对 pp 取模得到 iq+r≡0(modp)iq+r\equiv 0\pmod{p}

若 ii 不为 pp 的倍数, 则 rr 不为 0 , 因此 r−1r^{-1} 存在.

在上式两边乘 i−1r−1i^{-1}r^{-1} 得到 qr−1+i−1≡0(modp)qr^{-1}+i^{-1}\equiv 0\pmod{p} , 即

r−1≡−qr−1=−r−1⌊pi⌋(modp)r^{-1}\equiv -qr^{-1}=-r^{-1}\left\lfloor \dfrac{p}{i}\right\rfloor\pmod{p}

为了防止答案为负数, 使用 r−1(p−⌊pi⌋)r^{-1}(p-\left\lfloor \frac{p}{i}\right\rfloor) 代替 −r−1⌊pi⌋-r^{-1}\left\lfloor \frac{p}{i}\right\rfloor .

时间复杂度: O(n)\mathcal{O}(n)

inv[1] = 1;
for (int i = 2; i <= n; ++i)
inv[i] = inv[p % i] * (p - p / i) % p;

线性求逆元: 倒推法#

先直接求解 n!n! 的逆元, 然后利用 ((n−1)!)−1≡(n!)−1⋅n(modp)((n-1)!)^{-1}\equiv(n!)^{-1}\cdot n\pmod{p} 倒推求得 1!∼(n−1)!1!\sim (n-1)! 的逆元.

接着再利用 n−1≡(n!)−1⋅(n−1)!(modp)n^{-1}\equiv (n!)^{-1}\cdot (n-1)!\pmod{p} 求解 1∼n1\sim n 的逆元.

例题#

「POJ 1845」Sumdiv

首先利用整数惟一分解定理将 AA 表示为 A=p1r1p2r2⋯pnrnA=p_1^{r_1}p_2^{r_2}\cdots p_n^{r_n} .

则 ABA^B 约数和为

(1+p1+p12+⋯+p1B⋅r1)(1+p2+p22+⋯+p2B⋅r2)⋯(1+pn+pn2+⋯+pnB⋅rn)(1+p_1+p_1^2+\cdots +p_1^{B\cdot r_1})(1+p_2+p_2^2+\cdots+p_2^{B\cdot r_2})\cdots(1+p_n+p_n^2+\cdots+p_n^{B\cdot r_n})

可以发现, 每一个括号里都是一个等比数列求和, 以 pip_i 为例, 它的和可以写成 piB⋅ri+1−1pi−1\dfrac{p_i^{B\cdot r_i+1}-1}{p_i-1} , 然后我们可以利用快速幂求解分子 piB⋅ri+1 mod 9901p_i^{B\cdot r_i+1}\bmod{9901} , 这时若 pi−1>(piB⋅ri+1−1) mod 9901p_i-1>(p_i^{B\cdot r_i+1}-1)\bmod{9901} , 我们会得到 00 , 这显然是错的, 而模数 99019901 正好为素数, 因此考虑用 pi−1p_i-1 的逆元与分子的结果相乘来代替除法.

当 pi−1p_i-1 为 99019901 的倍数时不存在逆元, 这时我们可以发现 pi≡1(mod9901)p_i\equiv 1\pmod{9901} , 因此 1,pi,pi2,⋯ ,piB⋅ri+1≡1(mod9901)1, p_i, p_i^2, \cdots, p_i^{B\cdot r_i+1}\equiv 1\pmod{9901} , 所以 1+pi+pi2+⋯+piB⋅ri≡B⋅ri+1(mod9901)1+p_i+p_i^2+\cdots+p_i^{B\cdot r_i}\equiv B\cdot r_i+1\pmod{9901} .

线性同余方程#

形如 ax≡c(modm)ax\equiv c\pmod{m} 的方程,称为线性同余方程。

  1. 朴素算法 将 x=1,2,⋯ ,m−1x=1, 2, \cdots, m-1 一次带进去验证即可,这个朴素算法的复杂度取决于 mm 。
  2. 扩展欧几里得算法 可以将方程看作 ax+my=cax+my=c ,然后利用扩展欧几里得方法求解。 根据裴蜀定理,当且仅当 gcd⁡(a,m)∣c\gcd{(a, m)}|c 时方程有解。 令 d=gcd⁡(a,m)d=\gcd(a, m) ,则方程一共有 dd 个解,我们用扩展欧几里得算法求得特解 x0x_0 ,则方程的通解 xi=x0+i⋅md(i=0,1,⋯ ,d−1)x_i=x_0+i\cdot \dfrac{m}{d}(i=0, 1, \cdots, d-1) 。
  3. 欧拉定理 令 d=gcd⁡(a,m)d=\gcd{(a, m)} ,若 d∤cd \nmid c 则方程无解。 然后令 a′=ad,c′=cd,m′=mda'=\dfrac{a}{d}, c'=\dfrac{c}{d}, m'=\dfrac{m}{d} ,则 gcd⁡(a′,m′)=1\gcd{(a', m')}=1 ,原方程变为 a′x≡c′(modm′)a'x\equiv c'\pmod{m'} ,由欧拉定理,a′φ(m′)≡1(modm′)a'^{\varphi(m')}\equiv 1\pmod{m'} ,在方程两边分别乘上上式,得到 a′x≡c′a′φ(m′)(modm′)a'x\equiv c'a'^{\varphi(m')}\pmod{m'} ,即 x≡c′a′φ(m′)−1(modm′)x\equiv c'a'^{\varphi(m')-1}\pmod{m'} ,于是我们得到原方程的特解 x0=dc′a′φ(m′)−1x_0=dc'a'^{\varphi(m')-1} ,因此原方程的解为 xi=x0+i⋅m′(i=1,2,⋯ ,d−1)x_i=x_0+i\cdot m'(i=1, 2, \cdots,d-1) 。

例题#

线性组合

对应整数数列 A1,A2,⋯ ,AnA_1, A_2, \cdots, A_n 是否存在 X1,X2,⋯ ,XnX_1, X_2, \cdots, X_n , 使得 A1X1+A2X2+⋯+AnXn=CA_1X_1+A_2X_2+\cdots+A_nX_n=C ,其中 gcd⁡(A1,A2,⋯ ,An)∣C(n≥2)\gcd{(A_1, A_2, \cdots, A_n)}\mid C(n\ge2) 。如有,请找出一组整数解 (x1,x2,x3,x4)(x_1, x_2, x_3, x_4) 满足 12x1+24x2+18x3+15x4=312x_1+24x_2+18x_3+15x_4=3 .

题中的方程是 n 元形式的扩展欧几里得方程,我们尝试将 n 元逐步降为二元得到最终解。

设 d=gcd⁡(A1,A2,⋯ ,An)d=\gcd{(A_1, A_2, \cdots, A_n)} ,令 C′=Cd,Ai′=Aid(i=1,2,⋯ ,n)C'=\dfrac{C}{d},A_i'=\dfrac{A_i}{d}(i=1, 2, \cdots, n) ,首先将方程变形为 A1′X1+A2′X2+⋯+An′Xn=C′A_1'X_1+A_2'X_2+\cdots+A_n'X_n=C' ,此时满足 gcd⁡(A1′,A2′,⋯ ,An′,C′)=1\gcd{(A_1', A_2', \cdots, A_n', C')}=1 。

然后我们考虑求解方程 A1′X1+gcd⁡(A2′,A3′,⋯ ,An′)Y1=C′A_1'X_1+\gcd(A_2', A_3', \cdots, A_n')Y_1=C' ,利用扩展欧几里得方法求得特解 X1,Y1X_1,Y_1 ,由于题中仅要求得到一组解,因此我们只取特解即可,然后再以同样的方法求解 A2′X2+A3′X3+⋯+An′Xn=gcd⁡(A2′,A3′,⋯ ,An′)Y1A_2'X_2+A_3'X_3+\cdots+A_n'X_n=\gcd(A_2', A_3', \cdots, A_n')Y_1 便可以实现逐渐降元了。

线性同余方程组(模互素)#

考虑形如 x≡ai(modmi)x\equiv a_i\pmod{m_i} 的若干个线性同余方程联合得到的方程组,例如

{x≡2(mod3)x≡3(mod5)x≡5(mod7)\begin{cases} x &\equiv& 2\pmod{3} \\ x &\equiv& 3\pmod{5} \\ x &\equiv& 5\pmod{7} \end{cases}

一种可行的解法是令 x=3y+2x=3y+2 ,然后将方程 (2)(2) 改写成 y≡2(mod5)y\equiv 2\pmod{5} ,接着再令 y=5z+2y=5z+2 代入方程 (3)(3) 得到 z≡4(mod7)z\equiv 4\pmod{7} ,再令 z=7k+4z=7k+4 ,最后我们可以得到解 x≡68(mod105)x\equiv68\pmod{105} 。

中国剩余定理#

若线性同余方程组 x≡ai(modmi)(i=1,⋯ ,n)x\equiv a_i\pmod{m_i}(i=1, \cdots, n) 的模数 mim_i 两两互素,则 xx 在  mod M(M=∏i=1nmi)\bmod{M}(M=\prod_{i=1}^n m_i) 下有唯一解。

令 Mi=MmiM_i=\dfrac{M}{m_i} ,有 gcd⁡(Mi,mi)=1\gcd{(M_i, m_i)}=1 ,因此 MiM_i 在  mod mi\bmod{m_i} 下的逆元存在,设其为 tit_i ,于是有 aiMiti≡ai(modmi),aiMiti≡0(modmj)(j≠i)a_iM_it_i\equiv a_i\pmod{m_i},a_iM_it_i\equiv0\pmod{m_j}(j\not= i) 。

可以得到解 x≡∑i=1naiMiti(modM)x\equiv\sum_{i=1}^na_iM_it_i\pmod{M} 。

//China Remainer Theorem
int CRT(const int a[], const int m[], int n) {
int M = 1, ret = 0;
for (int i = 1; i <= n; ++i) M *= m[i];
for (int i = 1; i <= n; ++i) {
int ti = getinv(m[i], a[i]), Mi = M / m[i];
ret = (ret + a[i] * ti * Mi % M) % M;
}
return ret;
}
//利用 exgcd 求逆元
int getinv(int a, int b) {
int x, y;
exgcd(a, b, x, y);
return x;
}

线性同余方程组(模不互素)#

对于模不互素的线性同余方程组

{x≡a1(modm1)x≡a2(modm2)⋯x≡an(modmn)\begin{cases} x &\equiv a_1\pmod{m_1} \\ x &\equiv a_2\pmod{m_2} \\ &\cdots \\ x &\equiv a_n\pmod{m_n} \end{cases}

考虑求解方程数量为 2 的情形,当方程数量大于 2 时迭代求解。

{x≡a1(modm1)x≡a2(modm2)\begin{cases} x &\equiv a_1\pmod{m_1} \\ x &\equiv a_2\pmod{m_2} \end{cases}

设 y=x−a1y=x-a_1 ,则方程组变为

{y≡0(modm1)y≡a2−a1(modm2)\begin{cases} y &\equiv 0 &\pmod{m_1} \\ y &\equiv a_2-a_1 &\pmod{m_2} \end{cases}

设 d=gcd⁡(m1,m2)d=\gcd{(m_1, m_2)} ,根据裴蜀定理,若 d∤(a2−a1)d \nmid (a_2-a_1) ,则方程组无解,否则令 y′=yd,a′=a2−a1d,mi′=m1d(i=1,2)y'=\dfrac{y}{d},a'=\dfrac{a_2-a_1}{d}, m_i'=\dfrac{m_1}{d}(i=1,2) ,有

{y′≡0(modm1′)y′≡a′(modm2′)\begin{cases} y' &\equiv{0} &\pmod{m_1'} \\ y' &\equiv{a'} &\pmod{m_2'} \end{cases}

此时 gcd⁡(m1′,m2′)=1\gcd{(m_1', m_2')}=1 ,令 y′=km1′y'=km_1' ,再由欧拉定理可得 k≡a′m1′φ(m2′)−1(modm2′)k\equiv{a'm_1'^{\varphi(m_2')-1}}\pmod{m_2'} ,于是 y≡da′m1′φ(m2′)(moddm1′m2′)y\equiv{da'm_1'^{\varphi{(m_2')}}}\pmod{dm_1'm_2'} ,最后代回去可以得到 x≡(a2−a1)m1′φ(m2′)+a1(moddm1′m2′)x\equiv{(a_2-a_1)m_1'^{\varphi{(m_2')}}+a_1}\pmod{dm_1'm_2'} 。

例题#

「POJ 2891」Strange Way to Express Integers

算法和上述一致。

假设我们已经通过迭代求解得到前 k−1k-1 个方程的一个解 x0x_0 ,令 M=∏i=1k−1miM=\prod_{i=1}^{k-1}m_i ,则 x=x0+i⋅Mx=x_0+i\cdot M 是前 k−1k-1 个方程的通解。

考虑第 kk 个方程,我们可以将其改写为 x0+t⋅M≡ak(modmk)x_0+t\cdot M\equiv{a_k}\pmod{m_k} ,即 t⋅M≡ak−x0(modmk)t\cdot M\equiv{a_k-x_0}\pmod{m_k} ,接下来找到一个合适的 tt 即可,也就是求解一个同余方程了,利用欧拉定理求解即可。

高次同余方程#

第一类高次同余方程#

形如 ax≡b(modp)a^x\equiv{b}\pmod{p} 的方程称为第一类高次同余方程,其中 gcd⁡(a,p)=1\gcd(a, p)=1 。

BSGS#

解决这一类方程主要采用 BSGS (Baby Step Giant Step) 算法。

将 xx 写成 x=kt−m(0≤m≤t−1)x=kt-m(0\le m\le t-1) 的形式,则原方程可变形为 (at)k≡b⋅am(modp)(a^t)^k\equiv{b\cdot a^m\pmod{p}} 。

假设 tt 已知,那么我们只需枚举 kk ,然后计算相应的 b⋅amb\cdot a^m ,判断是否满足变形后的等式即可。

因为在枚举 kk 的过程中 mm 的取值也在变化,但 mm 的取值范围是不变的,因此我们可以预处理所有可能的 b⋅amb\cdot a^m 值,用一个 Hash 表储存。

由欧拉定理可知,有 aφ(p)≡1(modp)a^{\varphi(p)}\equiv{1}\pmod{p} ,而 φ(p)<p\varphi(p)<p ,因此从 1~p ,模 pp 意义下 aa 的幂至少完成了一次循环,所以最小整数解 x<px<p ,进而我们可以从 00 到 pt\dfrac{p}{t} 枚举 kk ,而 m∈[0,t−1]m\in[0,t-1] ,因此时间复杂度为 O(pt+t)\mathcal{O}(\dfrac{p}{t}+t) ,当 t=pt=\sqrt{p} 时复杂度最小。

时间复杂度:O(2p)\mathcal{O}(2\sqrt{p})

int BSGS(int a, int b, int p) {
b %= p;
if (a % p == 0) return b ? 1 : -1;
map <int, int> hash;
int t = sqrt(p) + 1;
for (int i = 0; i < t; ++i) {
int val = (long long)b * power(a, i, p) % p;//快速幂
hash[val] = i;
}
a = power(a, t, p);
for (int i = 0; i <= t; ++i) {
int val = power(a, i, p);
int j = hash.find(val) == hash.end() ? -1 : hash[val];
if (j >= 0 && i * t - j >= 0) return i * t - j;
}
return -1;
}

第二类高次同余方程#

形如 xk≡b(modp)x^k\equiv{b}\pmod{p} 的方程称为第二类高次同余方程。

首先引入阶和原根的概念,这一部分和抽象代数相关,我目前还不会 QAQ 。

阶#

满足同余式 an≡1(modp)a^n\equiv{1}\pmod{p} 的最小整数 nn 称为 aa 模 pp 的阶,记作 δp(a)\delta_p(a) 。

由欧拉定理可知,当 gcd⁡(a,p)=1\gcd(a, p)=1 时,有 aφ(p)≡1(modp)a^{\varphi(p)}\equiv{1}\pmod{p} ,因此阶的存在性得证。

性质 1 :a,a2,⋯ ,aδp(a)a,a^2,\cdots,a^{\delta_p(a)} 模 mm 两两不同余。

性质 2 :若 an≡1(modp)a^n\equiv{1}\pmod{p} ,则 n∣δp(a)n \mid \delta_p(a) 。

​ 推论 :若 am≡an(modp)a^m\equiv{a^n}\pmod{p} ,则 m≡n(modδp(a))m\equiv{n}\pmod{\delta_p(a)} 。

性质 3 :设 p∈N∗, a,b∈Z,gcd⁡(a,p)=gcd⁡(b,p)=1p\in\mathbb{N}^*,\, a,b\in\mathbb{Z},\gcd(a,p)=\gcd(b,p)=1 ,则 δp(ab)=δp(a)δp(b)\delta_p(ab)=\delta_p(a)\delta_p(b) 的充要条件是 gcd⁡(δp(a),δp(b))=1\gcd(\delta_p(a),\delta_p(b))=1 。

性质 4 :设 k∈N,p∈N∗,a∈Z,gcd⁡(a,p)=1k\in\mathbb{N},p\in\mathbb{N}^*,a\in\mathbb{Z},\gcd(a,p)=1 ,则 δp(ak)=δp(a)gcd⁡(δp(a),k)\delta_p(a^k)=\dfrac{\delta_p(a)}{\gcd(\delta_p(a),k)} 。

原根#

设 p∈N∗,a∈Zp\in\mathbb{N}^*,a\in\mathbb{Z} ,若 gcd⁡(a,p)=1\gcd(a,p)=1 ,且 δp(a)=φ(p)\delta_p(a)=\varphi(p) ,则称 aa 为模 mm 的原根。

以下基于 pp 为质数的情况进行讨论。

如何判断 aa 是否是 pp 的原根?

由费马小定理,方程 ax≡1(modp)a^x\equiv{1}\pmod{p} 的一个解为 x=p−1x=p-1 ,因此最小整数解 xmin∣(p−1)x_{min}\mid (p-1) ,而满足 xmin=p−1x_{min}=p-1 的整数 aa 是 pp 的原根,所以我们逐个枚举 p−1p-1 的约数 kk ,如果只有当 k=p−1k=p-1 时满足 ak≡1(modp)a^k\equiv{1}\pmod{p} ,则 aa 是 pp 的原根。

下面考虑求解 xk≡b(modp)x^k\equiv{b}\pmod{p} 。

由阶的性质 1 ,存在唯一的正整数 mm ,满足 am≡b(modp),0≤m≤p−1a^m\equiv{b}\pmod{p},0\le m\le p-1 ,其中 aa 是 pp 的原根,mm 可以由第一类高次同余方程求出。

同样,存在唯一正整数 yy ,使得 x≡ay(modp)x\equiv{a^y}\pmod{p} ,于是上述方程变为 aky≡am(modp)a^{ky}\equiv{a^m}\pmod{p} 。

由阶的性质 2 的推论,ky≡m(modp−1)ky\equiv{m}\pmod{p-1} ,于是我们求解这个线性同余方程得到 yy 便可以得到 xx 。

基础数论复习
https://f1a3h.moe/posts/basic-number-theory/
作者
f1a3h
发布于
2023-08-29
许可协议
CC BY-NC-SA 4.0