莫比乌斯反演的计算
从别人课件上扒下来的(qwq
问题:
已知 \(f(1) \cdots f(n)\), 且 \(g = f * \mu\), 算 \(g(1) \cdots g(n)\)。
解法1
按照定义计算, 即直接按照\(g(n) = \sum_{d|n} f(d) \mu(\frac{n}d)\)计算。
代码(伪):
for(int i=1; i<=n; ++i)
for(int j=1; j<=n/i; ++j)
g[i*j] += f[i] * mu[j];
复杂度是 \(O(n \log n)\) 。
解法2
定义数论函数
\[q_i(n) =
\begin{cases}
1 \quad n=1 \\
-1 \quad n = p_i \\
0 \quad else
\end{cases}
\]
其中 \(p_i\) 是第 \(i\) 个素数。
可以发现\(\mu = q_1 * q_2 * q_3 * \cdots\), 因此\(g = f * q_1 * q_2 * q_3 * \cdots\) 。
要把一个函数卷上 \(q_i\) , 只需要 \(O(\frac{n}{p_i})\) 的时间, 因此总复杂度就是 \(\sum_{p \leq n} \frac{n}p = O(n \log \log n)\) 。
代码(伪)
for(int i=1; i<=n; ++i) g[i] = f[i];
for(int i=1; i<=pr_cnt; ++i)
for(int j = n/prime[i]; j>0; --j) //j由大到小循环的原因类似0/1背包的优化qwq
g[j * prime[i]] -= g[j];