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)\),且常数很小。
标签:lfloor,right,frac,limits,数论,rfloor,小记,left From: https://www.cnblogs.com/BINYU/p/18038201