数论函数小记

这篇文章是上了 \(\rm yyc\) 的课之后得到的一些心得和总结。

高维点视角下的整除关系:

我们可以将一个数 \(x\) 唯一分解为 \(\prod_{i = 1}^{+\infty}p_i^{x_i}\) 的形式(其中 \(p_i\) 都是素数)。注意到每一种素数互不干扰,于是可以把每一种不同的素数看成立体空间的一维,把 \(x\) 看做一个高维点 \(p_x = (x_1, x_2, ....)\)

从而有: \(m | n \Leftrightarrow \forall i, m_i \le n_i\),即 \(p_m \le p_n\)。(注意这里比较的是偏序关系)。

接下来我们定义函数 \(f\) 的约数求和形式:

\[(\operatorname{Lsum}(f))(n) = \sum_{d|n}f(d) = \sum_{p_d \le p_n} f(d) \]

注意到这个求和式的本质实际上是高位前缀和,于是我们可以依次考虑每一维并对每一维分别做前缀和。这样就做到 \(O(n \log \log n)\) 求和了。

同样的,我们定义倍数求和 \((\operatorname{Rsum}(f))(n) = \sum_{n | d}f(d) = \sum_{p_n \le p_d} f(d)\)

有前缀和,自然我们就会考虑差分。定义 \(f\) 的约数差分为:

\[(\operatorname{Lsum}(\operatorname{Ldif}(f)))(n) = f(n) \]

即前缀和的逆操作,倍数差分定义也是相同的。但是有这个定义式我们不足以了解约数差分函数的具体情况。容易发现 \(\operatorname{Ldif} * \operatorname{I} = f\),从而 \(\operatorname{Lidf} = f * \mu\)

从而倍数差分也不难联想到是 \(\operatorname{Rdif}(n) = \sum_{n | d} \mu(d)f(\frac{d}{n})\),这个带入证明即可。

Luogu2714 四元组统计

“如果你还慢慢推式子,那你就输了。”

\(x\)\(a\) 中出现的次数为 \(cnt_x\)。先做一遍倍数求和得到 \(\operatorname{Rsum}\)。那么对于一个 \(x\),四个数都是 \(x\) 的倍数的四元组个数为 \(C_{cnt_x}^4\)

再做一遍倍数差分,答案是 \(\operatorname{Rdif}(1)\),没了。。。

反演动机:

反演动机即“迫害 xxx”,xxx 可以是 \(\gcd\) 或者 $ [x\perp y]$ 之类的。主要还是培养直觉吧。

Coprime Box

Statement:

维护一个集合 \(S\),支持如下三个操作:

  • \(S\) 中加入 \(x\)
  • \(S\) 中删除 \(x\)
  • 给出 \(y\),求 \(\sum_{x \in S} [x \perp y]\)

Solution:

看到 \([x \perp y]\) 就可以迫害它了,注意到 \([ x \perp y] = e(\gcd(x, y))\)。于是有:

\[\begin{aligned} \sum_{x \in S}[x \perp y] &= \sum_{x \in S} \sum_{d | y, d | x} {\mu(d)}\\ &= \\ &= \sum_{d|y} \mu(d) \sum_{d | x} 1 \\ &= \sum_{d | y} \mu(d) cnt_d \end{aligned} \]

其中 \(cnt_d\)\(d\) 的倍数中在集合 \(S\) 中的个数。

Luogu4449 于神之怒加强版

注意到 \(\gcd\) 的出现,直接去迫害 \(\gcd\)

\[\begin{aligned} \sum_{i = 1}^n\sum_{j = 1}^m \gcd(i, j)^k &= \sum_{d = 1}^n d^k \sum_{d | i} \sum_{d | j} [\gcd(i, j) = d] \\ &= \sum_{d = 1}^n d^k \sum_{i = 1}^{\lfloor\frac{n}{d} \rfloor} \sum_{j = 1}^{\lfloor\frac{m}{d} \rfloor} [\gcd(i, j) = 1] \\ &= \sum_{i = 1}^n (id_k * \mu)(d)\lfloor \frac{n}{d} \rfloor \lfloor \frac{m}{d} \rfloor \end{aligned} \]

\(f = id_k * \mu\),卷出来 \(f\) 整除分块即可。

整除差分:

整除分块可以快速处理被除数不变除数变化的整除问题,其核心在于对于 \(\lfloor \frac{n}{d} \rfloor\) 的值来说,\(d\) 依次取遍 \([1,n]\) 的所有值的过程中它的值变化次数很少。而整除差分解决的问题是对于一个不变的除数,当被除数即 \(n\)\(n - 1 \rightarrow n\) 时,通过充分利用 \(n - 1\) 的信息得出 \(n\) 的答案。

  • Lemma: \(\lfloor \frac{n - 1}{d} \rfloor \ne \lfloor \frac{n}{d} \rfloor \Leftrightarrow d | n\),且此时 \(\lfloor \frac{n - 1}{d} \rfloor = \lfloor \frac{n}{d} \rfloor + 1\)

通过这个观察我们可以知道,不论是 \(n\)\(d\) 两者任意一个变化,只要剩下那个值固定,那么其实剩下那个东西的变化次数实际上很少,那么我们就可以减少大量不必要的计算来优化复杂度了。

CF915G Coprime Arrays

\[\begin{aligned} Ans_i &= \sum_{a_1 = 1}^i .... \sum_{a_n = 1}^i [\gcd(a_1, ..., a_n) = 1]\\ &= \sum_{a_1 = 1}^i .... \sum_{a_n = 1}^i \sum_{d|a_1, d|a_2..., d|a_n} \mu(d)\\ &= \sum_{d = 1}^i \mu(d) \sum_{d | a_1} ... \sum_{d | a_n} 1\\ &= \sum_{d = 1}^i \mu(d) \lfloor \frac{i}{d} \rfloor^n \end{aligned} \]

预处理 \(id_n\),不难在 \(O(\sqrt n)\) 复杂度求解一个 \(Ans_i\)。但是这样还是不足以解决问题,

注意到每次从 \(i - 1 \rightarrow i\) 的过程中,对于 \(d(1 \le d \le i)\) 只有被除数发生了改变,而且这样的变化对于 \(\lfloor \frac{i}{d} \rfloor\) 的值其实影响不大。具体的,对于 \(\lfloor \frac{i}{d} \rfloor\),只有 \(d | i\)\(d\)\(\lfloor \frac{i}{d} \rfloor\) 发生了变化。

于是我们考虑差分:

\[\begin{aligned} Ans_i - Ans_{i - 1} &= \sum_{d = 1}^i \mu(d)(\lfloor \frac{i}{d} \rfloor^n - \lfloor \frac{i - 1}{d} \rfloor ^ n)\\ &= \sum_{d | i} \mu(d)(\lfloor \frac{i}{d} \rfloor ^ n- \lfloor \frac{i - 1}{d} \rfloor ^ n) \end{aligned} \]

这就不难 \(O(n \log n)\) 计算了。

posted @ 2024-08-08 15:52  Little_corn  阅读(10)  评论(0编辑  收藏  举报