初等数论进阶
本讲内容:狄利克雷卷积体系、杜教筛、Powerful Number 筛、Min_25 筛、二次剩余(Cipolla)、原根与高次剩余、扩展 BSGS、Pollard-Rho、类欧几里得、扩展 Lucas 完整实现、Stern–Brocot 树与 Pell 方程。
建议课时:6 课时。
0. 地图
| 节 | 主题 | 解决什么问题 |
|---|---|---|
| 1 | 狄利克雷卷积与狄利克雷前缀和 | 积性函数的代数结构,\(O(n\log\log n)\) 求 \(\sum_{d\mid n}f(d)\) |
| 2 | 莫比乌斯反演的高阶套路 | \(\sum\sum f(\gcd)\)、\(\prod\) 形式、多维 |
| 3 | 杜教筛 | 亚线性求 \(\varphi, \mu\) 等的前缀和,\(O(n^{2/3})\) |
| 4 | Powerful Number 筛 | 用 \(O(\sqrt n)\) 个点修正杜教筛能算的函数 |
| 5 | Min_25 筛 | 任意"\(f(p)\) 是多项式"的积性函数前缀和,\(O(n^{3/4}/\log n)\) |
| 6 | 二次剩余 | 模质数开平方 |
| 7 | 原根、指标与高次剩余 | \(x^k \equiv a\) 的全部解 |
| 8 | 扩展 BSGS 与 Pohlig–Hellman | 离散对数的非互质与光滑情况 |
| 9 | Pollard-Rho | \(10^{18}\) 级别质因数分解 |
| 10 | 类欧几里得 | \(\sum\lfloor\frac{ai+b}{c}\rfloor\) 及其二次形式 |
| 11 | 扩展 Lucas | 模合数的组合数 |
| 12 | Stern–Brocot、Pell、其他 | 分母最小的分数、二次不定方程 |
1. 狄利克雷卷积
1.1 定义与代数性质
- 交换律、结合律成立。
- 单位元 \(\epsilon(n) = [n = 1]\)。
- 逆元:\(f(1) \ne 0\) 时存在唯一 \(f^{-1}\) 使 \(f * f^{-1} = \epsilon\),递推\[f^{-1}(n) = -\frac{1}{f(1)}\sum_{d \mid n,\ d > 1} f(d)\,f^{-1}\!\left(\frac{n}{d}\right),\qquad f^{-1}(1) = \frac{1}{f(1)} \]
- 积性函数在卷积下封闭,积性函数的逆也是积性函数。
所以数论函数在 \((+, *)\) 下构成一个交换环,积性函数是其中的一个群。莫比乌斯反演就是"两边卷 \(\mu\)",因为 \(\mu = 1^{-1}\)。
1.2 恒等式速查
| 恒等式 | 含义 |
|---|---|
| \(\mu * 1 = \epsilon\) | \(\sum_{d\mid n}\mu(d) = [n=1]\) |
| \(\varphi * 1 = \text{id}\) | \(\sum_{d\mid n}\varphi(d) = n\) |
| \(1 * 1 = d\) | 约数个数 |
| \(\text{id} * 1 = \sigma\) | 约数和 |
| \(\text{id}_k * 1 = \sigma_k\) | \(k\) 次约数和 |
| \(\mu * \text{id} = \varphi\) | 由 \(\varphi * 1 = \text{id}\) 两边卷 \(\mu\) |
| \(\mu * d = 1\) | |
| \(\varphi * d = \sigma\) | \((\varphi * 1) * 1 = \text{id} * 1\) |
| \(\mu^2 * 1 = 2^{\omega}\) | 无平方因子约数个数 \(= 2^{\text{质因子种数}}\) |
1.3 \(O(n\log n)\) 求 \(f * g\) 的前 \(n\) 项
for (int i = 1; i <= n; i++)
for (int j = 1; i * j <= n; j++)
h[i * j] += f[i] * g[j];
调和级数 \(O(n\log n)\)。求 \(f^{-1}\) 同理,按 \(n\) 从小到大用 1.1 的递推。
1.4 狄利克雷前缀和 \(O(n\log\log n)\)
求 \(g(n) = \sum_{d\mid n}f(d)\) 对所有 \(n \le N\)。
把 \(n\) 看成质因子指数向量 \((e_{p_1}, e_{p_2}, \dots)\),"\(d \mid n\)"就是"每一维都 \(\le\)",所以 \(g\) 是 \(f\) 的高维前缀和,每个质数是一个维度。
for (int p : primes) // 对每个维度做一遍前缀和
for (int i = 1; i * p <= n; i++)
f[i * p] += f[i]; // i 递增,保证 f[i] 已含更低指数的贡献
复杂度 \(\sum_{p \le n} n/p = O(n\log\log n)\)。
逆变换(狄利克雷差分 / 莫比乌斯反演):\(i\) 递减,改成减法。
for (int p : primes)
for (int i = n / p; i >= 1; i--)
f[i * p] -= f[i];
后缀和(\(g(n) = \sum_{n\mid d}f(d)\)):for (i = n/p; i >= 1; i--) f[i] += f[i*p]。
这比 1.3 快一个 \(\log\),是"卷 \(1\)"和"卷 \(\mu\)"的最快实现。模板:洛谷 P5495。
1.5 例:\(O(n\log\log n)\) 线性筛之外求任意"卷 1"型函数
\(\sigma_k = \text{id}_k * 1\):初始化 \(f(i) = i^k\),做一次狄利克雷前缀和。
\(\varphi = \mu * \text{id}\):初始化 \(f(i) = i\),做一次狄利克雷差分。
2. 莫比乌斯反演的高阶套路
基础套路(换元 \(T = dk\)、整除分块)见容斥讲义。这里补充四类进阶形态。
2.1 \(\sum_{i}\sum_{j} f(\gcd(i,j))\) 的通用公式
推导:\(f(\gcd) = \sum_{d\mid\gcd}(f*\mu)(d)\)(莫比乌斯反演),交换求和。所以任何 \(f(\gcd)\) 求和都归结为求 \(f * \mu\) 的前缀和:
- \(f = \text{id}\):\(f * \mu = \varphi\)。
- \(f = [\cdot = 1]\):\(f * \mu = \mu\)。
- \(f = [\cdot \text{ 是质数}]\):\((f*\mu)(T) = \sum_{p \mid T}\mu(T/p)\),线性筛后 \(O(n\log\log n)\) 或用 1.4。
- \(f = d\):\(f * \mu = 1\)。
2.2 乘积形式:[SDOI2017] 数字表格
取对数思想:把 \(\sum\) 换成 \(\prod\),把系数换成指数。
预处理 \(G(T) = \prod_{d\mid T}F_d^{\mu(T/d)}\)(\(O(n\log n)\),\(\mu = -1\) 时乘逆元)及其前缀积,整除分块时用前缀积的商(乘逆元)。
2.3 带限制的求和:[SDOI2014] 数表
\(\sum_{i\le n}\sum_{j\le m}\sigma(\gcd(i,j))\,[\sigma(\gcd) \le a]\),多组询问 \(a\) 不同。
按 \(a\) 离线排序,\(\sigma\) 值也排序,双指针逐个"激活" \(\sigma(d) \le a\) 的 \(d\),激活时把 \(\sigma(d)\mu(T/d)\) 加到所有 \(T = kd\) 上(树状数组单点加,\(O(\frac{n}{d}\log n)\))。查询时整除分块 + 树状数组区间和。总 \(O(n\log^2 n + q\sqrt n\log n)\)。
套路:\((f*\mu)(T)\) 的定义式 \(\sum_{d\mid T}f(d)\mu(T/d)\) 中,\(f(d)\) 有限制时,把"激活 \(d\)"看成对 \(T\) 的倍数更新。
2.4 多维与非标准上界
\(\sum_{i}\sum_{j}\sum_{k}[\gcd(i,j,k)=1]\):\(\sum_d\mu(d)\lfloor n/d\rfloor^3\),三维整除分块与二维一样。
\(\sum_{i}\sum_{j}\gcd(i,j)\cdot[i\le n][j\le m][i \ne j]\) 等带附加条件:先去掉条件做完整求和,再单独减掉条件违反部分(通常是一维求和)。
\(\sum_{i}\sum_{j}\varphi(ij)\)(P4240 毒瘤之神的考验):\(\varphi(ij) = \dfrac{\varphi(i)\varphi(j)\gcd(i,j)}{\varphi(\gcd(i,j))}\),代入后 \(\sum_d \frac{d}{\varphi(d)}\sum_{k}\mu(k)S(\lfloor n/dk\rfloor)S(\lfloor m/dk\rfloor)\),其中 \(S\) 是 \(\varphi\) 的分段前缀和。令 \(T = dk\),内层 \(h(T) = \sum_{d\mid T}\frac{d}{\varphi(d)}\mu(T/d)\),然后 \(\sum_T h(T)S_1(n/T)S_2(m/T)\)。多组询问时对 \(T\) 整除分块仍有 \(O(\sqrt n)\) 段,每段需要 \(\sum_{T\in[l,r]}h(T)S(\lfloor n/T\rfloor)S(\lfloor m/T\rfloor)\),但 \(\lfloor n/T\rfloor\) 在段内是常数 \(a\)、\(\lfloor m/T\rfloor\) 是常数 \(b\),所以预处理 \(F[a][b][T] = \sum_{t\le T}h(t)S(a)S(b)\) 对小 \(a, b\)(\(\le B\))打表,大的暴力,根号分治。
3. 杜教筛
3.1 原理
要求 \(S(n) = \sum_{i=1}^{n}f(i)\)。找一个 \(g\),使得 \(f * g\) 和 \(g\) 的前缀和都好算。
把 \(d = 1\) 的项拆出来:
右边第二项整除分块,递归求 \(S(\lfloor n/d\rfloor)\),记忆化。
3.2 复杂度
\(S\) 只会在 \(\lfloor n/d\rfloor\) 处被调用,共 \(O(\sqrt n)\) 个值。不预处理时 \(O(n^{3/4})\);用线性筛预处理前 \(n^{2/3}\) 项后 \(O(n^{2/3})\)。
3.3 常用配对
| \(f\) | \(g\) | \(f * g\) | 递推式 |
|---|---|---|---|
| \(\mu\) | \(1\) | \(\epsilon\) | \(S(n) = 1 - \sum_{d\ge2}S(n/d)\) |
| \(\varphi\) | \(1\) | \(\text{id}\) | \(S(n) = \frac{n(n+1)}{2} - \sum_{d\ge2}S(n/d)\) |
| \(\varphi\cdot\text{id}\) | \(\text{id}\) | \(\text{id}^2\) | \(S(n) = \sum i^2 - \sum_{d\ge2}d\,S(n/d)\) |
| \(\varphi\cdot\text{id}^k\) | \(\text{id}^k\) | \(\text{id}^{k+1}\) | 同上推广 |
| \(\mu\cdot\text{id}\) | \(\text{id}\) | \(\epsilon\) | \(S(n) = 1 - \sum_{d\ge2}d\,S(n/d)\) |
| \(d\)(约数个数) | \(\mu\) | \(1\) | 需要 \(\mu\) 前缀和(再套一层杜教筛) |
判断 \(g\) 是否可用:\(g\) 要积性且前缀和 \(O(1)\)(幂函数),\(f * g\) 前缀和 \(O(1)\)。\(f(p)\) 是关于 \(p\) 的多项式时,通常取 \(g = \text{id}^k\) 使 \(f * g\) 在质数处为 \(p^{k'}\) 的简单形式。
3.4 代码
const int LIM = 2000000; // 约 n^{2/3}
int mu[LIM + 1], phi[LIM + 1]; ll smu[LIM + 1], sphi[LIM + 1];
unordered_map<ll, ll> Smu, Sphi;
ll sumMu(ll n) {
if (n <= LIM) return smu[n];
if (Smu.count(n)) return Smu[n];
ll res = 1;
for (ll l = 2, r; l <= n; l = r + 1) {
r = n / (n / l);
res -= (r - l + 1) * sumMu(n / l);
}
return Smu[n] = res;
}
ll sumPhi(ll n) { // 需要时取模
if (n <= LIM) return sphi[n];
if (Sphi.count(n)) return Sphi[n];
ll res = n * (n + 1) / 2;
for (ll l = 2, r; l <= n; l = r + 1) {
r = n / (n / l);
res -= (r - l + 1) * sumPhi(n / l);
}
return Sphi[n] = res;
}
unordered_map 可换成"按 \(\lfloor n/d\rfloor\) 的两段索引"数组(\(d \le \sqrt n\) 用 \(d\) 索引,否则用 \(n/d\) 索引),更快。模板:洛谷 P4213。
3.5 例题:洛谷 P3768 简单的数学题
\(\sum_{i}\sum_{j}ij\gcd(i,j) \bmod p\),\(n \le 10^{10}\)。
注意 $ij\gcd = \sum_{d\mid\gcd}d\varphi(d)\cdot ij / $ …… 更直接:\(\gcd(i,j) = \sum_{d\mid\gcd}\varphi(d)\),所以
需要 \(\varphi(d)d^2\) 的前缀和,取 \(g = \text{id}^2\),\(f*g = \text{id}^3\),杜教筛。
4. Powerful Number 筛
4.1 Powerful Number
\(n\) 是 PN 当且仅当每个质因子指数 \(\ge 2\)。所有 PN 可写成 \(a^2b^3\),所以 \(\le n\) 的 PN 只有 \(O(\sqrt n)\) 个。
4.2 原理
积性 \(f\),找积性 \(g\) 满足 \(g(p) = f(p)\)(只要求质数处相等)且 \(g\) 前缀和好算。令 \(h = f * g^{-1}\),则 \(h\) 积性且 \(h(p) = f(p) - g(p) = 0\),所以 \(h\) 只在 PN 处非零。
- 枚举 PN:DFS 枚举质数(\(\le\sqrt n\))及指数 \(\ge 2\),\(O(\sqrt n)\) 个。
- \(h(p^k)\):由 \(f(p^k) = \sum_{i=0}^{k}g(p^{k-i})h(p^i)\) 反解,对每个质数只需算到 \(p^k \le n\),总 \(O(\sqrt n\log n)\);若 \(h(p^k)\) 有闭式更好。
- \(S_g\):杜教筛或直接公式。
复杂度取决于 \(S_g\):若 \(S_g\) 是 \(O(1)\) 公式,总 \(O(\sqrt n)\);若杜教筛,\(O(n^{2/3})\)。
4.3 例题:LOJ 6053 简单的函数
\(f(p^e) = p \oplus e\),求前缀和。\(f(p) = p - 1\)(\(p\) 奇)或 \(3\)(\(p = 2\))。取 \(g = \varphi\)(\(g(p) = p - 1\)),\(g(2)\) 与 \(f(2)\) 不同,把 \(2\) 单独修正。\(S_\varphi\) 杜教筛。\(h(p^k)\) 用 4.2 反解。
4.4 与杜教筛的关系
杜教筛要求 \(f*g\) 好算;PN 筛只要求 \(g(p) = f(p)\),条件更松。杜教筛能做的 PN 筛都能做,且 PN 筛能处理 \(f(p^k)\) 任意的情况。
5. Min_25 筛
5.1 适用
积性 \(f\),且 \(f(p)\) 是关于 \(p\) 的低次多项式(或几个多项式之和),\(f(p^k)\) 可快速计算。\(n \le 10^{10}\) 左右。
5.2 第一阶段:质数处的前缀和
设 \(p_1 < p_2 < \cdots\) 为质数。定义
其中 \(f'\) 是完全积性函数(\(f'(p) = f(p)\) 的一个单项式,如 \(p^k\))。\(g(n, 0) = \sum_{i=2}^{n}f'(i)\) 用公式。递推:
含义:从"最小质因子 \(> p_{j-1}\) 的合数"里去掉"最小质因子恰为 \(p_j\)"的那些,它们是 \(p_j \times\)(最小质因子 \(\ge p_j\) 的数)。\(p_j^2 > n\) 时 \(g(n,j) = g(n,j-1)\)。
\(g(n, |P|)\) 就是 \(\sum_{p\le n}f'(p)\)。\(n\) 只取 \(\lfloor N/i\rfloor\) 的 \(O(\sqrt N)\) 个值,滚动数组。
\(f(p)\) 有多项时,对每个单项式各算一个 \(g\),最后线性组合。
5.3 第二阶段:全部数的前缀和
含义:按最小质因子 \(p_k\) 及其指数 \(e\) 分类,\(f(p_k^e)\cdot\)(剩余部分最小质因子 \(> p_k\))加上 \(p_k^{e+1}\) 本身。
答案 \(= S(N, 1) + f(1)\)。不需要记忆化,复杂度 \(O\!\left(\frac{n^{3/4}}{\log n}\right)\)。
5.4 代码(洛谷 P5325:\(f(p^k) = p^k(p^k - 1)\))
ll N, sq; int cnt;
ll pr[M], sp1[M], sp2[M]; // 质数、Σp、Σp² 前缀
ll w[M], g1[M], g2[M]; int tot; // w: 所有 ⌊N/i⌋;g1: Σp, g2: Σp²
int id1[M], id2[M];
int idx(ll x) { return x <= sq ? id1[x] : id2[N / x]; }
void sieve() { /* 线性筛出 ≤ sq 的质数,填 pr, sp1, sp2 */ }
ll S(ll n, int j) {
if (pr[j] > n) return 0;
int i = idx(n);
ll ans = (g2[i] - g1[i] - (sp2[j - 1] - sp1[j - 1]) + 2 * MOD) % MOD; // 质数处 f(p)=p²-p
for (int k = j; k <= cnt && pr[k] * pr[k] <= n; k++)
for (ll pe = pr[k], e = 1; pe * pr[k] <= n; pe *= pr[k], e++) {
ll fpe = pe % MOD * ((pe - 1) % MOD) % MOD;
ll fpe1 = pe * pr[k] % MOD * ((pe * pr[k] - 1) % MOD) % MOD;
ans = (ans + fpe * S(n / pe, k + 1) + fpe1) % MOD;
}
return ans;
}
int main() {
cin >> N; sq = sqrt((long double)N); sieve();
for (ll l = 1, r; l <= N; l = r + 1) { // 枚举 ⌊N/i⌋
r = N / (N / l); ll v = N / l;
w[++tot] = v;
ll vm = v % MOD;
g1[tot] = (vm * (vm + 1) / 2 - 1) % MOD; // Σ_{2..v} i
g2[tot] = (vm * (vm + 1) % MOD * (2 * vm + 1) % MOD * inv6 - 1) % MOD; // Σ_{2..v} i²
if (v <= sq) id1[v] = tot; else id2[N / v] = tot;
}
for (int j = 1; j <= cnt; j++)
for (int i = 1; i <= tot && pr[j] * pr[j] <= w[i]; i++) {
int k = idx(w[i] / pr[j]);
g1[i] = (g1[i] - pr[j] * (g1[k] - sp1[j - 1]) % MOD + MOD) % MOD;
g2[i] = (g2[i] - pr[j] * pr[j] % MOD * (g2[k] - sp2[j - 1]) % MOD + MOD) % MOD;
}
cout << (S(N, 1) + 1) % MOD << endl;
}
pr[cnt+1] 应设为一个大于 \(\sqrt N\) 的哨兵值以保证 pr[j] > n 的判断正确。
5.5 副产品:素数计数
取 \(f' = 1\),第一阶段的 \(g(n, |P|)\) 就是 \(\pi(n)\)。这是 Lucy_Hedgehog 算法,\(O(n^{3/4}/\log n)\),\(10^{11}\) 内秒出。
5.6 三种筛的选择
| 筛 | 条件 | 复杂度 | 优点 |
|---|---|---|---|
| 杜教筛 | 找得到 \(g\) 使 \(f*g\) 简单 | \(n^{2/3}\) | 最快 |
| PN 筛 | 找得到 \(g\) 使 \(g(p) = f(p)\) 且 \(S_g\) 好算 | \(\sqrt n\) 到 \(n^{2/3}\) | 处理 \(f(p^k)\) 任意 |
| Min_25 | \(f(p)\) 是多项式 | \(n^{3/4}/\log n\) | 最通用,不用找 \(g\) |
6. 二次剩余
6.1 定义与判别
\(p\) 为奇质数。若 \(x^2 \equiv a \pmod p\) 有解,称 \(a\) 是模 \(p\) 的二次剩余。
欧拉判别准则:\(a \not\equiv 0\) 时
勒让德符号 \(\left(\frac{a}{p}\right)\) 即上式的值。\(1..p-1\) 中恰有 \(\frac{p-1}{2}\) 个二次剩余。
二次互反律(了解):\(p, q\) 为不同奇质数,\(\left(\frac{p}{q}\right)\left(\frac{q}{p}\right) = (-1)^{\frac{p-1}{2}\cdot\frac{q-1}{2}}\)。
6.2 \(p \equiv 3 \pmod 4\) 的特殊情况
\(x = a^{\frac{p+1}{4}}\)。验证:\(x^2 = a^{\frac{p+1}{2}} = a\cdot a^{\frac{p-1}{2}} = a\)。
6.3 Cipolla 算法(一般情况)
- 随机 \(t\),直到 \(w = t^2 - a\) 是非二次剩余(期望 2 次)。
- 在扩域 \(\mathbb{F}_p[\sqrt w]\) 中计算 \(x = (t + \sqrt w)^{\frac{p+1}{2}}\),\(x\) 的 \(\sqrt w\) 系数为 0,常数项即答案。
证明:在 \(\mathbb{F}_p[\sqrt w]\) 中,\((\sqrt w)^p = \sqrt w\cdot w^{\frac{p-1}{2}} = -\sqrt w\)(因 \(w\) 非二次剩余)。由 Frobenius,\((t + \sqrt w)^p = t^p + (\sqrt w)^p = t - \sqrt w\)。于是
所以 \(x^2 = a\)。\(x \in \mathbb{F}_p\) 的证明:若 \(x = u + v\sqrt w\),\(v \ne 0\),则 \(x^2 = u^2 + v^2w + 2uv\sqrt w = a\) 要求 \(uv = 0\),\(u = 0\) 时 \(v^2 w = a\),与 \(w\) 非二次剩余、\(a\) 是二次剩余矛盾。\(\blacksquare\)
ll p, w;
struct Num { ll x, y; }; // x + y√w
Num mul(Num a, Num b) {
return {(a.x * b.x + a.y * b.y % p * w) % p, (a.x * b.y + a.y * b.x) % p};
}
Num pw(Num a, ll b) { Num r = {1, 0}; while (b) { if (b & 1) r = mul(r, a); a = mul(a, a); b >>= 1; } return r; }
ll sqrtMod(ll a) { // 返回一个根,无解返回 -1;另一根为 p - x
a %= p;
if (a == 0) return 0;
if (qpow(a, (p - 1) / 2, p) != 1) return -1;
ll t;
do { t = rng() % p; w = ((t * t - a) % p + p) % p; } while (qpow(w, (p - 1) / 2, p) != p - 1);
return pw({t, 1}, (p + 1) / 2).x;
}
模板:洛谷 P5491。两个根 \(x\) 与 \(p - x\),\(a = 0\) 时只有一个根。
6.4 模 \(p^k\) 与模合数:Hensel 提升
已知 \(x_0^2 \equiv a \pmod{p^k}\),求 \(x_1 \equiv x_0 + tp^k\) 使 \(x_1^2 \equiv a \pmod{p^{k+1}}\):
\(p \nmid 2x_0\) 时有唯一解。模合数先分解再 CRT。\(p = 2\) 需要单独讨论(模 8 的奇数二次剩余只有 1,解数为 4)。
6.5 应用
- 多项式开根:Newton 迭代的常数项需要 Cipolla。
- 斐波那契通项模 \(p\):\(\sqrt5\) 存在时(\(p \equiv \pm1 \pmod 5\)),\(F_n = \frac{1}{\sqrt5}(\varphi^n - \psi^n)\) 可直接快速幂。
- 判断 \(x^2 + y^2 = n\) 之类:\(-1\) 是模 \(p\) 二次剩余 \(\iff p \equiv 1 \pmod 4\)。
7. 原根、指标与高次剩余
7.1 阶与原根(复习加深)
- \(\delta_m(a) \mid \varphi(m)\);\(a^k \equiv 1 \iff \delta_m(a) \mid k\)。
- 原根存在 \(\iff m \in \{1, 2, 4, p^k, 2p^k\}\)。存在时原根个数为 \(\varphi(\varphi(m))\)。
- 求最小原根:枚举 \(g = 2, 3, \dots\),对 \(\varphi(m)\) 的每个质因子 \(q\) 检查 \(g^{\varphi(m)/q} \not\equiv 1\)。最小原根一般很小(\(O(m^{1/4})\) 级别,实践中几十以内)。
- 所有原根:\(g^k\),\(\gcd(k, \varphi(m)) = 1\)。
模板:洛谷 P6091。
7.2 指标:把乘法变加法
固定原根 \(g\),\(\{1, \dots, p-1\}\) 中每个 \(a\) 唯一写成 \(g^{\text{ind}(a)}\),\(\text{ind}(a) \in [0, p-2]\)。
\(\text{ind}\) 用 BSGS 求,\(O(\sqrt p)\)。所有关于乘法群的问题都可以转成模 \(p-1\) 的加法群问题。
7.3 \(N\) 次剩余:\(x^k \equiv a \pmod p\) 的全部解
设 \(x = g^y\),\(a = g^t\)(BSGS 求 \(t\))。则
线性同余方程:\(d = \gcd(k, p-1)\),\(d \nmid t\) 无解;否则 \(y_0 = \frac{t}{d}\left(\frac{k}{d}\right)^{-1} \bmod \frac{p-1}{d}\),全部解 \(y = y_0 + i\cdot\frac{p-1}{d}\),\(i = 0..d-1\),共 \(d\) 个。\(x = g^y\)。
vector<ll> nthRoot(ll k, ll a, ll p) { // x^k ≡ a (mod p), p 质数, a ≠ 0
ll g = primitiveRoot(p);
ll t = BSGS(g, a, p); // g^t ≡ a
ll x, y, d = exgcd(k, p - 1, x, y);
if (t % d) return {};
ll md = (p - 1) / d;
ll y0 = ((__int128)x * (t / d) % md + md) % md;
vector<ll> res;
for (ll i = 0; i < d; i++) res.push_back(qpow(g, y0 + i * md, p));
return res;
}
例题:SGU 261 Discrete Roots;洛谷 P2421 荒岛野人(不同题但同思路)。
7.4 \(a\) 是 \(k\) 次剩余的判定
\(a^{\frac{p-1}{\gcd(k, p-1)}} \equiv 1 \pmod p\)。(二次剩余的欧拉判别是 \(k = 2\) 的特例。)
8. 离散对数进阶
8.1 扩展 BSGS:\(\gcd(a, m) \ne 1\)
解 \(a^x \equiv b \pmod m\)。
反复取 \(d = \gcd(a, m)\):若 \(d \nmid b\) 无解;否则方程两边除以 \(d\):
重复直到 \(\gcd(a, m') = 1\),此时形如 \(C\cdot a^{x-k} \equiv b' \pmod{m'}\),把 \(C\) 的逆元乘过去,普通 BSGS 求 \(x - k\)。每步都要检查 \(C \equiv b'\)(即 \(x = k\) 是解)。
ll exBSGS(ll a, ll b, ll m) { // 最小非负 x,无解 -1
a %= m; b %= m;
if (b == 1 % m) return 0;
ll k = 0, C = 1, d;
while ((d = __gcd(a, m)) != 1) {
if (b % d) return -1;
b /= d; m /= d; k++;
C = C * (a / d) % m;
if (C == b) return k;
}
ll r = BSGS(a, b * inv(C, m) % m, m); // 普通 BSGS,需支持 m 非质数(只要 gcd(a,m)=1 即可)
return r < 0 ? -1 : r + k;
}
普通 BSGS 中 \(a^{-t}\) 的逆元用 exgcd 求(\(m\) 不一定是质数)。模板:洛谷 P4195。
8.2 Pohlig–Hellman(了解)
若 \(p - 1 = \prod q_i^{e_i}\) 的每个 \(q_i\) 都小(光滑),离散对数可以对每个 \(q_i^{e_i}\) 分别求(子群阶为 \(q_i^{e_i}\) 的 BSGS 只需 \(O(\sqrt{q_i})\)),再 CRT 合并。总 \(O(\sum e_i\sqrt{q_i})\)。这是为什么密码学要求 \(p - 1\) 有大质因子。
9. Pollard-Rho
9.1 思想
要找 \(n\) 的非平凡因子 \(d\)。取伪随机序列 \(x_{i+1} = x_i^2 + c \bmod n\)。模 \(d\) 看,这个序列在 \(O(\sqrt d)\) 步内进入循环(生日悖论),即存在 \(i \ne j\) 使 \(x_i \equiv x_j \pmod d\) 但(大概率)\(x_i \not\equiv x_j \pmod n\)。此时 \(\gcd(|x_i - x_j|, n)\) 就是 \(d\) 的倍数且 \(< n\)。
\(d \le \sqrt n\),所以期望 \(O(n^{1/4})\) 步。
9.2 实现要点
- Brent 判环 + 倍增:\(x\) 固定,\(y\) 走 \(1, 2, 4, \dots\) 步。
- 批量 gcd:把 \(|x - y|\) 累乘 127 次再做一次 gcd,减少 gcd 调用。若乘积变成 0(\(x = y\)),本轮失败,换 \(c\) 重来。
__int128乘法或long double快速乘。- 先用 Miller-Rabin 判质数,再递归分解。
ll rho(ll n) {
ll c = rng() % (n - 1) + 1, x = 0, y = 0, t = 1;
for (int goal = 1;; goal <<= 1, x = y, t = 1) {
for (int i = 1; i <= goal; i++) {
y = (mul(y, y, n) + c) % n;
t = mul(t, llabs(x - y), n);
if (i % 127 == 0) { ll d = __gcd(t, n); if (d > 1) return d; }
}
ll d = __gcd(t, n); if (d > 1) return d;
}
}
void factor(ll n, map<ll, int>& res) {
if (n == 1) return;
if (millerRabin(n)) { res[n]++; return; }
ll d;
do d = rho(n); while (d == n); // d == n 说明 t 变成 0,重试
factor(d, res); factor(n / d, res);
}
先把小质因子(\(\le 100\))试除掉可以显著加速。模板:洛谷 P4718。
10. 类欧几里得算法
10.1 问题
\(O(\log)\) 求。用途:直线下整点计数、\(\sum(ai + b)\bmod c\)、某些取模求和。
10.2 推导
情况一:\(a \ge c\) 或 \(b \ge c\)。 把整数部分提出:
情况二:\(a < c\),\(b < c\)。 令 \(m = \left\lfloor\frac{an + b}{c}\right\rfloor\)。交换求和:
\((a, c) \to (c \bmod a, a)\) 的变化和欧几里得算法一样,所以 \(O(\log)\)。
ll f(ll a, ll b, ll c, ll n) {
if (a == 0) return (b / c) * (n + 1);
if (a >= c || b >= c)
return (a / c) * n * (n + 1) / 2 + (b / c) * (n + 1) + f(a % c, b % c, c, n);
ll m = (a * n + b) / c;
return n * m - f(c, c - b - 1, a, m - 1);
}
10.3 二次形式
三者要同时递归(互相依赖)。结论(记 \(A = \lfloor a/c\rfloor\),\(B = \lfloor b/c\rfloor\),\(a' = a\bmod c\),\(b' = b\bmod c\),\(S_1 = \frac{n(n+1)}{2}\),\(S_2 = \frac{n(n+1)(2n+1)}{6}\)):
\(a \ge c\) 或 \(b \ge c\):
\(a < c\),\(b < c\)(\(m\) 同上,\(f', g', h'\) 表示参数 \((c, c-b-1, a, m-1)\)):
模板:洛谷 P5170。实现时把 \((f, g, h)\) 打包成结构体一起返回,每层只递归一次。
10.4 万能欧几里得(了解)
把"直线下方走格子"看成一个由 \(U\)(向上)和 \(R\)(向右)组成的序列,答案是这个序列在某个幺半群上的乘积。类欧的递归结构对序列做"欧几里得式"的重组,任何幺半群(矩阵、多项式)都可以套用。能处理 \(\sum \lfloor\cdot\rfloor^k\)、\(\sum A^{\lfloor\cdot\rfloor}B^i\) 等。模板:洛谷 P5170 加强版 / LOJ 6440。
11. 扩展 Lucas 完整实现
11.1 问题
\(\binom{n}{m} \bmod M\),\(M\) 不是质数但 \(M \le 10^6\) 左右(可分解,各 \(p^k\) 不大)。
11.2 步骤
- 分解 \(M = \prod p_i^{k_i}\)。
- 对每个 \(p^k\) 求 \(\binom{n}{m} \bmod p^k\)。
- CRT 合并。
11.3 \(\binom{n}{m} \bmod p^k\)
\(n!\) 写成 \(p^{v}\cdot F(n)\),\(F(n)\) 是"去掉所有 \(p\) 因子后的部分"。
- \(v\)(Legendre 公式):\(v_p(n!) = \sum_{j\ge1}\lfloor n/p^j\rfloor\)。
- \(F(n) \bmod p^k\):\(1..n\) 中不含 \(p\) 的数以 \(p^k\) 为周期,周期内乘积记 \(\Pi\);含 \(p\) 的数是 \(p, 2p, \dots\),提出 \(p\) 后是 \(1..\lfloor n/p\rfloor\),递归。
\(F\) 与 \(p\) 互质,逆元用 exgcd。
ll F(ll n, ll p, ll pk) {
if (!n) return 1;
ll res = 1;
for (ll i = 2; i <= pk; i++) if (i % p) res = res * i % pk; // 周期乘积(可预处理)
res = qpow(res, n / pk, pk);
for (ll i = 2; i <= n % pk; i++) if (i % p) res = res * i % pk;
return res * F(n / p, p, pk) % pk;
}
ll vp(ll n, ll p) { ll c = 0; while (n) n /= p, c += n; return c; }
ll Cpk(ll n, ll m, ll p, ll pk) {
if (m > n) return 0;
ll e = vp(n, p) - vp(m, p) - vp(n - m, p);
return F(n, p, pk) * inv(F(m, p, pk), pk) % pk * inv(F(n - m, p, pk), pk) % pk * qpow(p, e, pk) % pk;
}
ll exLucas(ll n, ll m, ll M) {
vector<ll> a, mods;
ll t = M;
for (ll p = 2; p * p <= t; p++) if (t % p == 0) {
ll pk = 1; while (t % p == 0) t /= p, pk *= p;
a.push_back(Cpk(n, m, p, pk)); mods.push_back(pk);
}
if (t > 1) a.push_back(Cpk(n, m, t, t)), mods.push_back(t);
return CRT(a, mods);
}
模板:洛谷 P4720。
11.4 Kummer 定理
\(v_p\left(\binom{n}{m}\right)\) = \(m\) 与 \(n - m\) 在 \(p\) 进制下相加的进位次数。推论:\(\binom{n}{m}\) 为奇数 \(\iff m \,\&\, (n-m) = 0 \iff m \subseteq n\)。
12. 其他工具
12.1 Stern–Brocot 树与 Farey 序列
从 \(\frac{0}{1}\) 和 \(\frac{1}{0}\) 出发,相邻两分数 \(\frac{a}{b}, \frac{c}{d}\) 之间插入中位分数 \(\frac{a+c}{b+d}\)。性质:
- 每个正有理数恰出现一次,且以最简形式出现。
- 相邻分数满足 \(bc - ad = 1\)。
- 树上从根到 \(\frac{p}{q}\) 的路径由欧几里得算法的商序列决定(左右走的次数)。
应用:区间 \((\frac{a}{b}, \frac{c}{d})\) 内分母最小的分数(洛谷 P5179)。递归:
- 若 \(\lfloor a/b\rfloor + 1 < c/d\)(即区间内有整数),答案是 \(\lfloor a/b\rfloor + 1\)。
- 若 \(a/b\) 和 \(c/d\) 有相同整数部分 \(k\),减去 \(k\) 后取倒数(区间翻转),递归,再倒回来加 \(k\)。
每步是欧几里得的一步,\(O(\log)\)。
Farey 序列 \(F_n\):分母 \(\le n\) 的所有最简分数按大小排列。相邻项 \(\frac{a}{b}, \frac{c}{d}\) 的下一项是 \(\frac{kc - a}{kd - b}\),\(k = \lfloor\frac{n + b}{d}\rfloor\)。可 \(O(1)\) 递推枚举。\(|F_n| = 1 + \sum_{i\le n}\varphi(i)\)。
12.2 Pell 方程
\(x^2 - Dy^2 = 1\)(\(D\) 非完全平方)。
- 有无穷多正整数解,最小解 \((x_1, y_1)\) 称基本解。
- 全部解:\(x_k + y_k\sqrt D = (x_1 + y_1\sqrt D)^k\),即\[x_{k+1} = x_1x_k + Dy_1y_k,\qquad y_{k+1} = x_1y_k + y_1x_k \]
- 基本解由 \(\sqrt D\) 的连分数展开得到;竞赛中 \(D\) 小可以暴力枚举 \(y\)。
\(x^2 - Dy^2 = -1\) 不一定有解;\(= N\) 的一般情况用基本解生成有限个"类"。
12.3 连分数
\(\frac{p}{q} = a_0 + \cfrac{1}{a_1 + \cfrac{1}{a_2 + \cdots}}\),\(a_i\) 是欧几里得算法的商。渐进分数 \(\frac{p_k}{q_k}\) 满足 \(p_k = a_kp_{k-1} + p_{k-2}\),\(q_k\) 同理,且 \(p_kq_{k-1} - p_{k-1}q_k = (-1)^{k-1}\)。渐进分数是"分母不超过 \(q_k\) 的最佳有理逼近"。
12.4 \(n!\bmod p\) 的快速计算(了解)
\(n < p\),\(p\) 大质数:分块 \(\prod_{i}(is + 1)\cdots(is + s)\),\(s = \sqrt p\),块乘积是关于 \(i\) 的 \(s\) 次多项式,多项式多点求值 \(O(\sqrt p\log^2 p)\)。威尔逊定理的推广用于 \(n \ge p\) 的情形。
12.5 数论分块的二维形态
\(\sum_{i=1}^{n}(n \bmod i)(m \bmod i)\)([清华集训2012] 模积和,洛谷 P2260):展开为 \(\sum(n - i\lfloor n/i\rfloor)(m - i\lfloor m/i\rfloor)\),需要 \(\sum i^2\lfloor n/i\rfloor\lfloor m/i\rfloor\),双变量整除分块 + 平方和公式。注意 \(i > \min(n,m)\) 的部分要单独处理。
13. 常见错误清单
- 狄利克雷前缀和的循环方向。 前缀和 \(i\) 递增,差分 \(i\) 递减。
- 杜教筛的 \(g(1)\)。 若 \(g(1) \ne 1\) 要除以 \(g(1)\)。
- 杜教筛的记忆化键。 只有 \(\lfloor n/d\rfloor\) 形式的参数会重复,用
map或两段数组,不要用n直接开数组。 - Min_25 第一阶段的枚举顺序。 外层质数、内层 \(w\),且 \(w_i < p_j^2\) 时停止(不是跳过)。
- Min_25 的
pr[cnt+1]哨兵。S函数中pr[j] > n需要哨兵才能在 \(j = cnt+1\) 时正确返回。 - Cipolla 忘记 \(a = 0\) 和 \(a\) 非二次剩余的判断,或随机 \(t\) 时 \(w = 0\)(\(t^2 = a\) 直接就是答案)。
- \(N\) 次剩余中模数是 \(p - 1\)。 指标在 \(\mathbb{Z}_{p-1}\) 中,不是 \(\mathbb{Z}_p\)。
- exBSGS 每步除 \(d\) 后忘记检查 \(C = b\)。 会漏掉 \(x = k\) 这个解。
- Pollard-Rho 的 \(t = 0\)。 必须重新随机 \(c\),否则返回 \(n\) 导致无限递归。
- 类欧的 \(a = 0\) 边界。 必须单独返回,否则 \(m\) 的计算会出错。
- 类欧的 \(g, h\) 不同时递归。 三者互相依赖,分开递归复杂度爆炸。
- 扩展 Lucas 的 \(F\) 用了 Wilson。 周期乘积不是 \(-1\)(模 \(p^k\) 时 Wilson 不成立),必须真的乘。
- Stern–Brocot 递归时整数部分处理。 区间含整数时直接返回,否则减整数部分再倒数。
14. 课堂练习
- 用狄利克雷前缀和在 \(O(n\log\log n)\) 内求 \(\sum_{i\le n}\sigma(i)\),写出初始化和循环。
- 证明 \(\mu * d = 1\) 和 \(\varphi * d = \sigma\)。
- 为 \(f = \mu\cdot\text{id}^2\) 找杜教筛的 \(g\),写出递推式。(答:\(g = \text{id}^2\),\(f*g = \epsilon\))
- 对 \(f(p^k) = p^k + k\) 设计 PN 筛:\(g\) 取什么?\(h(p^2)\) 是多少?
- 用 Min_25 框架求 \(\sum_{p\le n}p^2\)(只需第一阶段),说明 \(g(n, 0)\) 的公式。
- 手算 \(x^2 \equiv 2 \pmod 7\)。(答:\(7 \equiv 3 \pmod 4\),\(x = 2^2 = 4\),验证 \(16 \equiv 2\);另一根 3)
- 模 13 的最小原根是多少?\(x^3 \equiv 5 \pmod{13}\) 有几个解?(答:2;\(\gcd(3, 12) = 3\),\(5 = 2^9\),\(9 \bmod 3 = 0\),3 个解)
- 求 \(f(3, 1, 5, 4)\) 并用类欧递归验证。(答:\(\lfloor1/5\rfloor + \lfloor4/5\rfloor + \lfloor7/5\rfloor + \lfloor10/5\rfloor + \lfloor13/5\rfloor = 0+0+1+2+2 = 5\))
- 用 Kummer 定理判断 \(\binom{10}{3}\) 被 3 整除几次。(答:\(3 + 7\) 在三进制下 \(10 + 21\) 有 1 次进位,整除 1 次;\(\binom{10}{3} = 120 = 3\cdot40\) \(\checkmark\))
- 在 \((\frac{2}{5}, \frac{3}{7})\) 内找分母最小的分数。(答:\(\frac{5}{12}\))
- \(x^2 - 2y^2 = 1\) 的前三组正整数解。(答:\((3,2), (17,12), (99,70)\))
15. 推荐题单
| 难度 | 题目 | 考点 |
|---|---|---|
| 基础 | 洛谷 P5495 Dirichlet 前缀和 | 狄利克雷前缀和 |
| 基础 | 洛谷 P4213 【模板】杜教筛 | 杜教筛 |
| 基础 | 洛谷 P5491 【模板】二次剩余 | Cipolla |
| 基础 | 洛谷 P6091 【模板】原根 | 原根 |
| 基础 | 洛谷 P4195 【模板】扩展 BSGS | exBSGS |
| 基础 | 洛谷 P4718 【模板】Pollard-Rho | Pollard-Rho |
| 基础 | 洛谷 P5170 【模板】类欧几里得 | 类欧 \(f, g, h\) |
| 基础 | 洛谷 P4720 【模板】扩展卢卡斯 | exLucas |
| 基础 | 洛谷 P5179 Fraction | Stern–Brocot |
| 提高 | 洛谷 P3768 简单的数学题 | 杜教筛 + 莫反 |
| 提高 | 洛谷 P6055 [RC-02] GCD | 杜教筛 |
| 提高 | 洛谷 P3172 [CQOI2015] 选数 | 莫反 + 杜教筛 |
| 提高 | 洛谷 P5325 【模板】Min_25 筛 | Min_25 |
| 提高 | LOJ 6053 简单的函数 | Min_25 / PN 筛 |
| 提高 | 洛谷 P6156 简单题 | PN 筛 |
| 提高 | 洛谷 P3704 [SDOI2017] 数字表格 | 乘积形式莫反 |
| 提高 | 洛谷 P3312 [SDOI2014] 数表 | 离线 + 树状数组莫反 |
| 提高 | 洛谷 P2303 [SDOI2012] Longge 的问题 | \(\sum\gcd\) |
| 提高 | 洛谷 P2260 [清华集训2012] 模积和 | 二维整除分块 |
| 提高 | SGU 261 Discrete Roots | \(N\) 次剩余 |
| 挑战 | 洛谷 P4240 毒瘤之神的考验 | \(\varphi(ij)\) + 根号分治 |
| 挑战 | 洛谷 P5518 [MtOI2019] 幽灵乐团 | 三合一莫反 |
| 挑战 | 洛谷 P4619 [SDOI2018] 旧试题 | 莫反 + 三元环 |
| 挑战 | LOJ 6440 万能欧几里得 | 万能欧几里得 |
| 挑战 | 洛谷 P5325 加强 / LOJ 6235 | 素数计数 \(10^{11}\) |
附录:一页纸总结
选筛:有 \(g\) 使 \(f*g\) 简单 → 杜教;\(f(p^k)\) 怪但 \(f(p)\) 像已知函数 → PN;\(f(p)\) 多项式 → Min_25。

浙公网安备 33010602011771号