【笔记】莫比乌斯反演

0 约定

\([n]=[1,n]\cap\mathtt Z\)

1 数论分块

形如 $S(n)=\sum\limits_{i=1}^nf(i)g(\left \lfloor \dfrac{n}{i} \right \rfloor) $。

可以在 \(O(\sqrt n)\) 的时间复杂度内求解。


1.1 解法

  1. 对于 \(1\le i\le \sqrt n\)

    显然,\(i\) 最多 \(\sqrt n\) 种取值,故而 \(\left \lfloor \dfrac{n}{i} \right \rfloor\) 最多有 \(\sqrt n\) 种取值。

  2. 对于 \(\sqrt n<i\le n\)

    \(\left \lfloor \dfrac{n}{i} \right \rfloor\le\sqrt n\),最多亦有 \(\sqrt n\) 种取值。

综上,如果可以 \(O(1)\) 得到 \(f\) 的区间和,那么可以通过枚举 \(\left \lfloor \dfrac{n}{i} \right \rfloor\) 的取值,\(O(2\sqrt n)\approx O(\sqrt n)\) 求解。

具体代码如下:

int res = 0;
for (int i = 1, j; i <= n; i = j+1) {
    j = n/(n/i);
    res += (f(j) - f(i-1)) * g(n/i);
}

其中 \(j\) 为对于当前 \(i\) 满足 \(\left \lfloor \dfrac{n}{i} \right \rfloor=\left \lfloor \dfrac{n}{j} \right \rfloor\) 的最大的 \(j\)


2 莫比乌斯函数

对于一些函数 \(f(n)\),如果很难直接求出它的值,而容易求出其倍数和或约数和 \(g(n)\),那么可以通过莫比乌斯反演,简化运算得到 \(f(n)\) 的值。

2.1 定义

定义莫比乌斯函数:

\[\mu(n)= \begin{cases} 1&n=1\\ 0&n\text{ 含有平方因子}\\ (-1)^k&k\text{ 为 }n\text{ 的不同质因子个数}\\ \end{cases}\]

注:

  1. 「含有平方因子」是指存在 \(p\) 为质数,\(\alpha\) 为满足 \(p^{\alpha}=n\) 的最大整数,\(\alpha\ge2\)。eg. \(\mu(24)=0\)

2.2 性质

  1. \(\mu(n)\)不完全 积性函数,即 \(\mu(x)\mu(y)=\mu(xy)\) 当且仅当 \((x,y)=1\)

  2. 狄利克雷卷积 相关:

    1. \((\mu*\operatorname I)=\begin{cases} 1&n=1\\ 0&n\neq 1\\ \end{cases}=\varepsilon\)

      证明与下类似。

    2. \((\mu*\operatorname{Id})=\varphi\)

      证明:

      设:\(n=p_1^{\alpha_1}p_2^{\alpha_2}\cdots p_k^{\alpha_k}\)\(p\) 为质数,\(\alpha\) 为正整数。

      \[\begin{aligned} (\mu*\operatorname{Id})(n) &=\sum_{d|n}\mu(d)\dfrac n d\\ &\begin{array}{c} =\left(\mu(1)\frac{p_1^{\alpha_1}}{1}+\mu(p_1)\frac{p_1^{\alpha_1}}{p_1}+\cdots+\mu(p_1^{\alpha_1})\frac{p_1^{\alpha_1}}{p_1^{\alpha_1}}\right) \\ \hspace{1.5em}\vdots \\ \hspace{1.5em}\left(\mu(1)\frac{p_k^{\alpha_k}}{1}+\mu(p_k)\frac{p_k^{\alpha_k}}{p_k}+\cdots+\mu(p_k^{\alpha_k})\frac{p_k^{\alpha_k}}{p_k^{\alpha_k}}\right) \\ \end{array}&\text{【直接把括号展开,就可以发现她是对的】}\\ &=\left(p_1^{\alpha_1}-\frac{p_1^{\alpha_1}}{p_1}\right)\left(p_2^{\alpha_2}-\frac{p_2^{\alpha_2}}{p_2}\right)\cdots\left(p_k^{\alpha_k}-\frac{p_k^{\alpha_k}}{p_k}\right)&\text{【把 } \mu \text{ 的值带进去】}\\ &=\frac{(p_1-1)p_1^{\alpha_1}}{p_1}\times\frac{(p_2-1)p_2^{\alpha_2}}{p_2}\times\cdots\times\frac{(p_k-1)p_k^{\alpha_k}}{p_k}\\ &=(p_1-1)p_1^{\alpha_1-1}(p_2-1)p_2^{\alpha_2-1}\cdots(p_k-1)p_k^{\alpha_k-1}\\ &=\varphi(n)&\text{【 }\varphi\text{ 的一种公式计算法】} \end{aligned}\]


3 线性筛求莫比乌斯函数

线性质数筛(欧拉筛)的一大优势在于我们可以知道每个数的 最小质因子,从而通过递推线性求解 积性函数

void init (int _n) {
	for (int i = 2; i <= _n; i++) is_prime[i] = 1;
	mu[1] = 1;
	for (int i = 2; i <= _n; i++) {
		if (is_prime[i])
			prime.push_back(i),
			mu[i] = -1;
		for (int j : prime) {
			if (1ll*i*j > _n) break;
			is_prime[i*j] = 0;
			if (i%j == 0) {
				mu[i*j] = 0;
				break;
			}
			mu[i*j] = -mu[i];
		}
	}
}

4 莫比乌斯反演

设两个个数论函数 \(f(x),F(x)\),若有 \(F(x)=\sum_{d|x}f(d)\)

则有:

\[\begin{aligned} f(x)&=\sum_{d|x}\mu(d)F(\frac nd)%=\sum_{i=1}^{\left\lfloor \frac n x\right\rfloor}\mu(i)F(ix) \\ &=\sum_{d|x}\mu(\frac nd)F(d) \end{aligned} \]


5 例题

5.1 简单的数学题

5.1.1 Description

已知:\(n\)

求:

\[\left(\sum_{i=1}^n\sum\limits_{j=1}^n ij \gcd(i,j)\right) \bmod p \]

感性感知一下,\(\gcd(i,j)\) 的取值实际上很少,所以突破口在于枚举她的取值。

设:

\(f(d)=\sum\limits_{i,j\in[n]\wedge\gcd(i,j)=d}ij\)

\(F(x)=\sum_{d|x}f(d)\)

\(G(x)=\sum\limits_{i=1}^ni=\dfrac{n(n+1)}2\)

答案即为 \(Ans=\sum\limits_{d=1}^nf(d)d\)

下考虑求解 \(f(d)\)

\[\begin{aligned}F(d)&=\sum_{d|i}\sum_{d|j}ij\\ &=\sum_{d|i}i\times\sum_{d|j}j\\ &=\left(\sum_{i=1}^{\left\lfloor\frac n i\right\rfloor}id\right)^2\\ &=\left(G\left(\left\lfloor\frac n i\right\rfloor\right) d\right)^2\\ \end{aligned} \]

从而:

\[Ans=\sum\limits_{d=1}^nd\sum\limits_{i=1}^{\left\lfloor \frac n i\right\rfloor}\mu(i)F(ix) \]

推柿子:

\[\begin{aligned}\sum\end{aligned} \]

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int lim = 1e7;
int mu[lim+5], phi[lim+5];
bool is_prime[lim+5];
vector<int> prime;
ll _S[lim+5], inv2, inv6, ans, p, n;
unordered_map<ll, ll> S;
ll qpow (ll a, ll b) {
	ll res = 1;
	for (; b; b >>= 1, (a *= a) %= p)
		if (b & 1) (res *= a) %= p;
	return res;
}
void init (int _n) {
	for (int i = 2; i <= _n; i++) is_prime[i] = 1;
	phi[1] = 1;
	mu[1] = 1;
	for (int i = 2; i <= _n; i++) {
		if (is_prime[i])
			prime.push_back(i),
			phi[i] = i-1,
			mu[i] = -1;
		for (int j : prime) {
			if (1ll*i*j > _n) break;
			is_prime[i*j] = 0;
			if (i%j == 0) {
				phi[i*j] = j * phi[i];
				mu[i*j] = 0;
				break;
			}
			phi[i*j] = phi[j] * phi[i];
			mu[i*j] = -mu[i];
		}
	}
	for (int i = 1; i <= _n; i++)
		_S[i] = (_S[i-1] + 1ll*i*i%p * phi[i]%p) % p;
}
ll F1 (ll x) { return x%=p, x*(x+1)%p*inv2%p; }
ll F2 (ll x) { return x%=p, x*(x+1)%p*(x*2+1)%p*inv6%p; }
ll F3 (ll x) { return x%=p, F1(x) * F1(x) % p; }
ll solve (ll x) {
	if (x <= lim) return _S[x];
	if (S[x]) return S[x];
	ll res = F3(x);
	for (ll i = 2, j; i <= x; i = j+1) {
		j = x/(x/i);
		res = (res - solve(x/i) * (F2(j) - F2(i-1) + p) % p + p) % p;
	}
	return S[x] = res;
}
int main () {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> p >> n;
	inv2 = qpow(2, p-2), inv6 = qpow(6, p-2);
	init(lim);
	for (ll i = 1, j; i <= n; i = j+1) {
		j = n/(n/i);
		(ans += F1(n/i) * F1(n/i)%p * ((solve(j) - solve(i-1)+p)%p) % p) %= p;
	}
	cout << ans;
	return 0;
}

5.2 【模板】杜教筛


5.3 YY的GCD

posted @ 2024-01-24 21:54  CloudWings  阅读(11)  评论(0编辑  收藏  举报