莫比乌斯反演

这是莫比乌斯函数 \(\mu\) 的定义。

基础知识

首先定义 \([A]\),为:

如果 \(A\) 为真,那么 \([A]=1\)

否则 \([A]=0\)

于是现在有:

对于 \(\forall n\in N^+,\displaystyle \sum_{d|n} \mu(d)=[n=1]\)

给出证明:

分两类考虑
如果 \(n=1\),显然成立。
如果 \(n>1\)

此时对 \(n\) 做质因子分解,不妨设 \(n=\displaystyle \prod _{i=1}^{k}p_i^{\alpha_i}\)
不难发现,\(\displaystyle \sum_{d|n} \mu(d)=\sum_{d|n_0}\mu(d)\),其中 \(n_0=\displaystyle \prod_{i=1}^k p_i\)
固定一个质因子,不妨为 \(p_1\)
那么对于 \(\forall x| \displaystyle \frac {n_0} {p_1}\),都有 \(\mu(x)+\mu(p_0\times x)=0\)
注意到这里的 \(x\)\(p_0\times x\) 既不重合又不遗漏的包含了整个 \(n_0\) 的因数集。
于是 \(\displaystyle \sum_{d|n} \mu(d)=0\)

于是 \(\displaystyle \sum_{d|n}\mu(d)=[n=1]\)\(\square\)

考虑 Dirichlet 卷积

考虑有关 \(\mu\)Dirichlet 卷积:

如果 \(f(n)=\displaystyle \sum_{d|n} g(d)\)

那么,\(g(n)=\displaystyle \sum_{d|n}\mu(\frac n d)f(d)\)

现在给出证明:

\(f(n)=\displaystyle \sum_{d|n} g(d)\) 代入 \(\displaystyle \sum_{d|n}\mu(\frac n d)f(d)\),得到 :

\(\displaystyle \sum_{d|n}\mu(\frac n d)f(d)=\displaystyle \sum_{d|n}\mu(\frac n d)\sum_{d_0|d} g(d_0)\)

考虑改变枚举顺序:

\(\displaystyle \sum_{d|n}\mu(\frac n d)\sum_{d_0|d} g(d_0)=\displaystyle \sum_{d_0|n}g(d_0)\sum_{d_0|d|n}\mu(d)\)

单独考虑 \(\displaystyle \sum_{d_0|d|n}\mu(d)\),设 \(d=d_0\times x\),那么就有:

\(\displaystyle \sum_{d_0|d|n}\mu(d)=\sum_{x|\frac n {d_0}} \mu(x)=[\frac n {d_0} = 1]=[n = d_0]\)

所以,就有 \(\displaystyle \sum_{d_0|n}g(d_0)\sum_{d_0|d|n}\mu(d)=\sum_{d_0|n}g(d_0)[n=d_0]=g(n)\)

于是,\(\displaystyle \sum_{d|n}\mu(\frac n d)f(d)=g(n)\)\(\square\)

\(\mu\) 函数的性质

思考有关 \(\mu\) 函数的性质,根据定义,不难发现:

\(\forall a,b\in N^+\),且 \(\gcd(a,b)=1\),都有 \(\mu(ab)=\mu(a)\times\mu(b)\)

注意到这个东西正好可以在 线性筛 中被筛出,所以,此时得到了一个 \(O(n)\)\(\mu\) 的方法,其中 \(n\) 是值域大小。

#include<bits/stdc++.h>
using namespace std;
const int N=1e7+1000,M=1e7;
#define L(i,j,k) for(int i=j;i<=k;i++)
int T,n;
long long mu[N];
int prime[N],cnt;
bool isprime[N];

void xxs(){
	mu[1]=1;
	L(i,2,M){
		if(!isprime[i])prime[++cnt]=i,mu[i]=-1;
		L(j,1,cnt&&prime[j]*i<=M){
			isprime[prime[j]*i]=true;
			if(i%prime[j]==0)break;
			mu[i*prime[j]]=mu[i]*mu[prime[j]];
		}
	}
	L(i,1,M)mu[i]=mu[i]+mu[i-1];
}
int main(){
	ios::sync_with_stdio(0);
	xxs();
	cin>>T;
	while(T--){
		cin>>n;
		cout<<mu[n]<<'\n';
	}
	return 0;
} 

数论分块

考虑如何求出 \(\displaystyle \sum_{i=1}^n[\frac n i]\)

显然有一个 \(O(n)\) 的暴力,但是当 \(n\le 10^{14}\) 时,暴力却显得捉襟见肘。

考虑如何加快时间。

不难发现在所有的 \([\displaystyle \frac n i]\) 中,它的取值其实是很少的,那么只需要能够快速算出来每一种值的出现次数就可以了。

首先,说明一件事情:

对于 \(\forall n\in N^+,|\{[\displaystyle \frac n i] | i\in N^+,i\le n\}|\le [2\sqrt{n}]\)

证明:对于 \(i\) 分两类讨论:

\(i\le \sqrt{n}\) 时,总共只有 \(\sqrt{n}\) 个数,所以一共最多有 \(\sqrt{n}\) 个取值。

\(i> \sqrt{n}\) 时,\([\displaystyle \frac n i]\le \sqrt{n}\),此时 \([\displaystyle \frac n i]\) 最多只有 \([\sqrt{n}]\) 个不同取值。

所以一共最多有 \([\sqrt{n}]+[\sqrt{n}]\le [2\sqrt{n}]\) 个不同的取值。

这说明,如果能够在 \(O(1)\) 时间复杂度之内算出每一种数的出现次数,就可以 \(O(\sqrt{n})\) 计算 \(\displaystyle \sum_{i=1}^n[\frac n i]\) 的值了。

现在思考如何在 \(O(1)\) 时间算出每一个值的出现次数。

显然所有使 \([\displaystyle \frac n i]=[\frac n j]\) 成立的 \(i,j\) 应该是在一块的。

那么考虑已知整个块的左端点,算出整个块的右端点(因为可以由此递归解出下一个块的左端点)。

\[ # 例题 ## ``G\]

posted @ 2024-05-19 16:36  Pump_kin  阅读(26)  评论(0)    收藏  举报