数论小记

gcd

辗转相除法,也可以直接用 __gcd

线性筛

保证每个数只会被其最小的质数筛掉,复杂度 \(O(n)\),也可以用来处理积性函数,通常作为更复杂的筛法的预处理。

exgcd

可用于求解不定方程: \(ax + by = gcd(a,b)\)

推导如下:

\[ax + by = gcd(a,b) = gcd(b,a \bmod b) = bx'+(a \bmod b)y' \]

\[ax + by = bx' + \left(a - b \left\lfloor \frac{a}{b} \right\rfloor\right)y' \]

\[ax + by = ay' + b \left(x' - \left\lfloor \frac{a}{b} \right\rfloor y\right) \]

\[\therefore \begin{cases} x = y' \\ y = x' - \left\lfloor \frac{a}{b} \right\rfloor y \end{cases}\]

为一组合法解。

crt

用于求解线性同余方程组:

\[\begin{cases} x \equiv a_1 \pmod {m_1} \\ x \equiv a_2 \pmod {m_2} \\ \dots\\ x \equiv a_n \pmod {m_n} \\ \end{cases}\]

其中 \(m_1,m_2,\dots,m_n\) 两两互质。

\(P = \prod\limits_{i = 1}^{n} p_i\)

\(x\) 变化 \(\frac{P}{p_i}\) 只会对第 \(i\) 个同余方程产生影响。

考虑逐一满足所有方程。

\(\frac{P}{p_i}\) 在模 \(p_i\) 意义下的逆元为 \(inv_i\)

则有

excrt

个人认为比 crt 简单。

用于求解线性同余方程组:

\[\begin{cases} x \equiv a_1 \pmod {m_1} \\ x \equiv a_2 \pmod {m_2} \\ \dots\\ x \equiv a_n \pmod {m_n} \\ \end{cases}\]

其中 \(m_1,m_2,\dots,m_n\) 不需要满足两两互质

先考虑两个方程:

\[\begin{cases} x \equiv a_1 \pmod {m_1} \\ x \equiv a_2 \pmod {m_2} \\ \end{cases}\]

可转化为:

\[x = m_1 p + a_1 = m_2 q + a_2 \]

\[m_1 p - m_2 q = a_2 - a_1 \]

\(gcd(m_1,m_2) \nmid a_2 - a_1\) 则无解。

否则可以用 exgcd 找到一组合法 \(p,q\)

即可将两个方程化为一个:

\[x \equiv m_1 p + a_1 \pmod{\operatorname{lcm}(m_1,m_2)} \]

重复此过程即可。

Lucas

用于求解

\(C^n_m \bmod p\)

\(p\) 是质数。

\[C^n_m \bmod p = C ^ {\lfloor n/p \rfloor} _ {\lfloor m/p \rfloor} C ^ {n \bmod p} _ {m \bmod p} \bmod p \]

前面递归,后面直接算。

exLucas

用于求解

\(C^n_m \bmod P\)

\(P\) 不一定是质数

\(P\) 质因数分解:\(P = \prod\limits p_i^{k_i}\)

若已知 \(C^n_m \bmod p_i^{k_i}\),则可用 crt 求出 \(C^n_m \bmod P\)

下面考虑求 \(C^n_m \bmod p^k\)

\(x!\) 中质因子 \(p\) 的指数为 \(cnt_x\),则:

\[C^n_m \bmod p^k = \frac{\frac{n!}{p^{cnt_n}}}{\frac{m!}{p^{cnt_m}}\frac{(n - m)!}{p^{cnt_{n - m}}}}p^{cnt_n - cnt_m - cnt_{n - m}} \bmod p^k \]

考虑求 \(\frac{n!}{p^{cnt_n}} \bmod p^k\)

\(n = 19,p = 2,k = 3\) 为例:

\[19! = 2^9 (9!) \times (1 \times 3 \times 5 \times 7 \times 9 \times 11 \times 13 \times 15 \times 17 \times 19) \]

其中 \(2^9\) 一定会被 \(p^{cnt_n}\) 约掉,\(9!\) 可以递归求解,后面的部分有:

\[1 \times 3 \times 5 \times 7 \equiv 9 \times 11 \times 13 \times 15 \pmod {p^k} \]

所以我们可以按 \(p^k\) 分组,快速幂后乘上不满一组的数即可。

据此便可求出 \(C^n_m \bmod p^k\),即可求出 \(C^n_m \bmod P\)

优化:在\(k = 1\) 时,\(C^n_m \bmod p^k\) 可以用 Lucas 来求,特别是需要多次取模时。

BSGS

求满足 \(a^x \equiv b \pmod {m}\) 的最小的 \(x\)\(\gcd(a,m) = 1\)

\(x = p \lfloor \sqrt{m} \rfloor - q,q \le \sqrt{m}\),可知:

\[a^{p \lfloor \sqrt{m} \rfloor} \equiv a^q \times b \pmod {m} \]

对于右边用 map 预处理,枚举 \(p\) 检查是否有满足的 \(q\) 即可。

exBSGS

求满足 \(a^x \equiv b \pmod {m}\) 的最小的 \(x\) 或报告无解。

\(d_1 = \gcd(a,m)\),若 \(d_1 = 1\) 则问题变为 BSGS,若\(d_1 \nmid b\) 则无解,否则原方程可变为:

\[\frac{a}{d_1} a^{x - 1} \equiv \frac{b}{d_1} \pmod {\frac{m}{d_1}} \]

\[\frac{a}{d_1} a^{x - 1} \equiv \frac{b}{a} \pmod {\frac{m}{d_1}} \]

\(d_2 = \gcd(a,\frac{m}{d_1})\) …… 重复以上过程直到 \(\gcd(a,\frac{m}{d_1 d_2 \dots d_k}) = 1\) ,此时 \(\frac{a}{d_1 d_2 \dots d_k}\) 在模 \(\frac{m}{d_1 d_2 \dots d_k}\) 意义下有逆元。

\(b' = \frac{b}{a^k},m'= \frac{m}{d_1 d_2 \dots d_k},x' = x - k\),原方程变为:

\[a^{x'} \equiv b' \pmod {m'},\gcd(a,m') = 1 \]

可用 BSGS 求解。

注意:需特判 \([1,k]\) 中是否有合法的 \(x\)

莫比乌斯反演

利用 \(\sum\limits_{d \mid n} \mu(d) = [n = 1]\) 将一些带条件的式子转化为不带条件的式子。

杜教筛

用于求数论函数前缀和。

\(S(i) = \sum\limits_{i = 1}^{n} f(i)\),求 S(n)。

构造一个数论函数 \(g\)

则有:

\[\begin{align} \sum\limits_{i = 1}^{n}(f * g)(i) &= \sum\limits_{i = 1}^{n} \sum\limits_{d | n} g(d) f\left(\frac{n}{d}\right)\\ &= \sum\limits_{i = 1}^{n} \sum\limits_{j = 1}^{\left\lfloor\frac{n}{i}\right\rfloor} g(i) f(j)\\ &= \sum\limits_{i = 1}^{n} g(i)S\left( \left\lfloor \frac{n}{i} \right\rfloor \right) \end{align}\]

\[\therefore g(1)S(n) = \sum\limits_{i = 1}^{n}(f * g)(i) - \sum\limits_{i = 2}^{n} g(i)S\left( \left\lfloor \frac{n}{i} \right\rfloor \right) \]

若我们能快速的计算 \(\sum\limits_{i = 1}^{n}(f * g)(i)\)\(\sum\limits_{i = 1}^{n} g(i)\),就可用数论分块求出 \(S(n)\)

实际操作时,可以用线性筛预处理出一部分来降低时间复杂度。

Min_25 筛

求积性函数 \(f\) 的前缀和。\(f\) 需满足 \(f(p)\) 是一个关于 \(p\) 的多项式且 \(f(p^k)\) 可以快速计算。

约定:

\(lpf_i\) 表示 \(i\) 的最小质因子,\(lpf_1 = +\infty\)

发现最难求的 \(f(i)\) 是含有比 \(\lfloor\sqrt{n}\rfloor\) 大的质因子的 \(i\)

考虑把质数与合数的贡献分开,用比 \(\lfloor\sqrt{n}\rfloor\) 小的质数筛出所有质数的 \(f\)

由于 \(f(p)\) 是关于 \(p\) 的多项式,所以我们可以把它拆成一个个单项式来做。

定义 \(g(n,j)\) 表示 \(\sum\limits_{i = 1}^{n}[i \in \mathbb{P} \operatorname{or} lpf_i \ge p_i]f(i)\)\(g_k(n,j)\) 表示 \(\sum\limits_{i = 1}^{n}[i \in \mathbb{P} \operatorname{or} lpf_i \ge p_i]i^k\)

易知:\(g_k(n,0) = \sum\limits_{i = 1}^{n} i^k\)

我们最终需要的 \(g_k(n,j)\) 需要满足 \(p_j^2 > n\),此时就没有满足条件的合数了,留下来的数就全是质数。

考虑从 \(g_k(n,j - 1)\)\(g_k(n,j)\) 转移。

容易发现 \(g_k(n,j)\) 相较于 \(g_k(n,j - 1)\) 少了 \(lpf = p_j\) 的合数,由于 \(i^k\) 是完全积性函数,我们可以直接将 \(p_j\) 提出来,得到转移式:

\[g_k(n,j) = g_k(n,j - 1) - p_j^k\left(g_k\left(\left\lfloor\frac{n}{p_j}\right\rfloor,j - 1\right)-g_k(p_j - 1,j - 1)\right) \]

注意质数也包含在了 \(g_k\left(\left\lfloor\frac{n}{p_j}\right\rfloor,j - 1\right)\) 中,但我们不能筛掉质数,所以要将质数的贡献 \(g_k(p_j - 1,j - 1)\) 减去。

发现我们不需要 \(g\) 的过程,所以可以将 \(g\) 的第二维滚动掉,下面将最终的 \(g(n,j)\) 简记为 \(g(n)\)

接下来就可以求合数的部分了。

我们仿照 \(g\) 的定义,定义 \(S(n,j)\) 表示 \(\sum\limits_{i = 2}^{n}[lpf_i > p_j]f(i)\),我们要的答案就是 \(S(n,0) + 1\)

现在考虑转移:枚举所有可能的 \(lpf\) 及其次数,可以得到转移式:

\[S(n,i) = g(n) + \sum\limits_{p_j^k \le n,j > i}f(p_j^k)\left(S\left(\left\lfloor \frac{n}{S} \right\rfloor,j\right) + [k > 1]\right) \]

\(g(n)\):代表 \(n\) 以内质数的贡献和,用之前处理的单项式拼出来。

\(f(p_j^k)\)\(f\) 就是题目中的 \(f\),因为不满足完全积性的性质,所以要枚举最小质因子的指数,注意区分这里的 \(p_j^k\) 和求 \(g\) 时的 \(p_j^k\)

\(S\left(\left\lfloor \frac{n}{S} \right\rfloor,j\right)\):比 \(p_j\) 大的质因子的贡献,递归求解。

\([k > 1]\)\(p_j\) 也可以作为最大的质因子,所以要加 \(1\),又由于质数已经算了,所以在 \(k = 1\) 时不能加这个 \(1\)

边界条件就是 \(n \le p_i\),此时没有合法的数,所以此时 \(S(n,i) = 0\)

这个过程不用记忆化时间复杂度也是对的。

现在唯一的问题是如果把 \([1,n]\)\(g\) 都求出来会让时间复杂度回归了 \(O(n)\)

可以发现 \(g_k(p_j - 1,j - 1)\) 实际上就是质数的贡献,由于 \(p_j ^ 2 \le n\),所以我们可以用线性筛处理这个式子。

此时求 \(g(n)\) 所需要用到的 \(g\) 都可以写成 \(g\left(\left\lfloor \frac{n}{k} \right\rfloor\right)\) 的形式,求 \(S\) 所需要的 \(g\) 也都可以写成 \(g\left(\left\lfloor \frac{n}{k} \right\rfloor\right)\) 的形式。

所以所有用到的 \(g\) 的都可以写成 \(g\left(\left\lfloor \frac{n}{k} \right\rfloor\right)\) 的形式。

这说明用到的 \(g\) 只有 \(O(\lfloor \sqrt n \rfloor)\) 个,可以离散化:

对于满足 \(\left\lfloor \frac{n}{k} \right\rfloor \le \lfloor \sqrt{n} \rfloor\)\(\lfloor \frac{n}{k} \rfloor\),我们用一个数组在 \(\left\lfloor \frac{n}{k} \right\rfloor\) 处存储其离散化后的下标。

对于另外的 \(\left\lfloor \frac{n}{k} \right\rfloor\),我们用另外一个数组在 \(\left\lfloor \frac{n}{\left\lfloor \frac{n}{k} \right\rfloor} \right\rfloor\) 处存储其离散化后的下标。

两个数组长度均为 \(O(\lfloor \sqrt{n} \rfloor)\),每次查询下标只需要 \(O(1)\),且常数很小。

posted @ 2024-03-01 12:18  BlNYU  阅读(5)  评论(0编辑  收藏  举报