莫比乌斯反演

这是莫比乌斯函数 \(\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\) 应该是在一块的。
那么考虑已知整个块的左端点,算出整个块的右端点(因为可以由此递归解出下一个块的左端点)。

浙公网安备 33010602011771号