Loading

学习笔记——莫比乌斯反演

前言

时隔一年,学了点多项式基础,然后来搞搞数论。学一下颓柿子。

数论分块

是用莫反解决问题的基础。

形式:如果有式子 \(\sum\limits_{i=1}^ng(\lfloor\dfrac{n}{i}\rfloor)\) 需要求值,我们能在 \(O(\sqrt{n})\) 的复杂度内求出上面这个式子的值。即需要求的东西中需要有带整除的值,所以也叫整除分块。

考虑到当 \(n\) 很大的时候,我们这个 \(\lfloor\dfrac{n}{i}\rfloor\) 的取值是非常少的。可以证明取值不超过 \(2\sqrt{n}\) 个。

$\texttt{Proof}$

\(i\le\sqrt{n}\),那么就算每个 \(i\) 都有一个不同的 \(\lfloor\dfrac{n}{i}\rfloor\),那总数也不超过 \(\sqrt{n}\) 个。

\(i\ge\sqrt{n}\),那么有 \(\lfloor\dfrac{n}{i}\rfloor\le\dfrac{n}{i}\le\sqrt{n}\),所以也不超过 \(sqrt{n}\) 个。

综上,这样的取值不超过 \(2\sqrt{n}\) 个。

接下来我们需要一个性质:\(\lfloor\dfrac{\lfloor\frac{x}{a}\rfloor}{b}\rfloor=\lfloor\dfrac{x}{ab}\rfloor\)

证明略。

然后就有如下结论:对于每个 \(\lfloor\dfrac{n}{i}\rfloor\) 相等的块,其左端点为 \(l\) 的话,右端点就是 \(\lfloor\dfrac{n}{\lfloor\frac{n}{l}\rfloor}\rfloor\)

$\texttt{Proof}$

\(k=\lfloor\dfrac{n}{i}\rfloor\),有 \(\lfloor\dfrac{n}{i}\rfloor\le \dfrac{n}{i}\)

\(\lfloor\dfrac{n}{k}\rfloor\ge\lfloor\dfrac{n}{\frac{n}{i}}\rfloor=i\)。所以最大的 \(i\) 就是 \(\lfloor\dfrac{n}{k}\rfloor=\lfloor\dfrac{n}{\lfloor\frac{n}{i}\rfloor}\rfloor\)

这样一来,代码就很好写了。

$\texttt{Code}$
void solve(){
	ll n;cin>>n;
	ll ans=0;
	for(ll l=1,r;l<=n;l=r+1){
		r=n/(n/l);ans+=(r-l+1)*(n/l);
	}cout<<ans<<'\n';
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	int T;for(cin>>T;T--;)solve();
	return 0;
}
$\texttt{Code}$
int main()
{
	ll n,k,ans;
	scanf("%lld%lld",&n,&k);ans=n*k;
	for(ll l=1,r;l<=n;l=r+1){
		if(k/l) r=min(k/(k/l),n);else r=n;
		ans-=(l+r)*(r-l+1)/2*(k/l);
	}printf("%lld\n",ans);
}

以及一个显然的结论:

\[\sum_{d|n}f(d)=\sum_{d|n}f(\dfrac{n}{d}) \]

前置知识

你需要会素数筛(好歹是线性筛吧),然后唯一分解定理。

然后是调和级数求和是 \(n\log n\) 也得知道。

数论函数

定义:若对于 \(a\bot b\),有 \(f(ab)=f(a)f(b)\),则 \(f(x)\) 为积性函数。

单位函数

\[\epsilon(x)=[x=1] \]

任何函数卷积上这个函数都是那个函数本身。单位函数是积性的。

除数函数

\[\sigma_k(x)=\sum_{d|n}d^k \]

\(\sigma_0{(x)}\)\(x\) 的约数个数,\(\sigma_1{(x)}\) 为约数和,简称 \(\sigma(x)\)。除数函数也是积性的。

欧拉函数

内容比较多,主要是关于欧拉定理和欧拉筛的,\(\varphi(x)\) 表示小于 \(x\) 的与 \(x\) 互质的数的个数。

\[\varphi(x)=x\prod_{i=1}^s(1-\dfrac{1}{p_i}) \]

其中 \(p_i\) 表示 \(x\) 的第 \(i\) 个质因子。当然也可以用欧拉筛出欧拉函数。

幂函数

\[Id_k(x)=x^k \]

狄利克雷卷积

一种特殊的因数卷积。

\[h(x)=\sum_{d|n}f(d)g(\dfrac{n}{d}) \]

\(f(x)\)\(g(x)\) 的狄利克雷卷积,记做 \(h=f*g\)

性质:满足结合律,并且如果 \(f,g\) 都是积性函数,那么 \(f*g\) 也是积性函数。

一些常见的卷积:\(\mu*1=\epsilon,Id=\varphi*1\)

也就是:

\[[x=1]=\sum_{d|x}\mu(d) \]

\[x=\sum_{d|x}\varphi(d) \]

莫比乌斯函数

\[\mu(x)=\begin{cases}0&x=k^2a\\1&n=1\\(-1)^k&x=p_1p_2p_3\cdots p_k\end{cases} \]

这东西由于也是积性的,可以用线性筛求。

莫比乌斯反演

\(g=f*1\),则 \(g\)\(f\) 的莫比乌斯变换。

那么 \(f\) 就是 \(g\) 的莫比乌斯逆变换。

莫比乌斯反演定理指出:\(g=f*1\Leftrightarrow f=g*\mu\)

一些例题

题单

题单中指出了莫比乌斯反演的三种形式,也就是最常见的三种。


Case1:

\[\begin{aligned}\sum_{x=1}^n\sum_{y=1}^m[\gcd(x,y)=1]&=\sum_{x=1}^n\sum_{y=1}^m\sum_{d|\gcd(x,y)}\mu(d)\\&=\sum_{x=1}^n\sum_{y=1}^m\sum_{d|x}\sum_{d|y}\mu(d)\\&=\sum_{d=1}^{\min(n,m)}\mu(d)\sum_{x=1}^n\sum_{y=1}^m[d|x][d|y]\\&=\sum_{d=1}^{\min(n,m)}\mu(d)\lfloor\dfrac{n}{d}\rfloor\lfloor\dfrac{m}{d}\rfloor\end{aligned} \]

然后你整除分块搞一下就可以 \(O(\sqrt{n})\) 求了。


Case2:

\[\sum_{x=1}^n\sum_{y=1}^m\gcd(x,y)=\sum_{x=1}^n\sum_{y=1}^m\sum_{d|\gcd(x,y)}\varphi(d) \]

然后和上面那个同理,最后

\[\sum_{x=1}^n\sum_{y=1}^m\gcd(x,y)=\sum_{d=1}^{\min(n,m)}\varphi(d)\lfloor\dfrac{n}{d}\rfloor\lfloor\dfrac{m}{d}\rfloor \]


Case3:

\[\begin{aligned}\sum_{x=1}^n\sum_{y=1}^mf(\gcd(x,y))&=\sum_{d=1}^{\min(n,m)}f(d)\sum_{x=1}^n\sum_{y=1}^m[\gcd(x,y)=d]\\&=\sum_{d=1}^{\min(n,m)}f(d)\sum_{x=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{y=1}^{\lfloor\frac{m}{d}\rfloor}[\gcd(x,y)=1]\\&=\sum_{d=1}^{\min(n,m)}f(d)\sum_{k=1}^{\min(\lfloor\frac{n}{d}\rfloor,\lfloor\frac{m}{d}\rfloor)}\mu(k)\lfloor\dfrac{\lfloor\frac{n}{d}\rfloor}{k}\rfloor\lfloor\dfrac{\lfloor\frac{m}{d}\rfloor}{k}\rfloor\\&=\sum_{d=1}^{\min(n,m)}f(d)\sum_{k=1}^{\min(\lfloor\frac{n}{d}\rfloor,\lfloor\frac{m}{d}\rfloor)}\mu(k)\lfloor\dfrac{n}{kd}\rfloor\lfloor\dfrac{m}{kd}\rfloor\end{aligned} \]

接着令 \(T=kd\),则有:

\[\begin{aligned}\sum_{x=1}^n\sum_{y=1}^mf(\gcd(x,y))&=\sum_{T=1}^{\min(n,m)}\lfloor\dfrac{n}{T}\rfloor\lfloor\dfrac{m}{T}\rfloor\sum_{d|T}f(d)\mu(\dfrac{T}{d})\end{aligned} \]

P2568 GCD

本题要求:

\[\begin{aligned}\sum_{p\in P}\sum_{x=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{y=1}^{\lfloor\frac{n}{p}\rfloor}[\gcd(x,y)=1]&=\sum_{p\in P}\sum_{x=1}^{\lfloor\frac{n}{p}\rfloor}\mu(x)\lfloor\dfrac{\lfloor\frac{n}{p}\rfloor}{x}\rfloor^2\end{aligned} \]

然后暴力枚举直接做就好了。

$\texttt{Code}$
const int MAXN=1e7+10;
int mu[MAXN],pr[MAXN],p[MAXN],cnt,n;
void init(){
	p[1]=1;mu[1]=1;
	rep(i,2,n){
		if(!p[i]) pr[++cnt]=i,mu[i]=-1;
		for(int j=1;j<=cnt&&i*pr[j]<=n;j++){
			p[i*pr[j]]=1;
			if(i%pr[j]){
				mu[i*pr[j]]=-mu[i];
			}else{mu[i*pr[j]]=0;break;}
		}
	}
}
int pre[MAXN];
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n;init();
	rep(i,1,n) pre[i]=pre[i-1]+mu[i];
	int ans=0;
	rep(i,1,cnt){
		int m=n/pr[i],cur=0;
		for(int l=1,r;l<=m;l=r+1){
			r=m/(m/l);cur+=(pre[r]-pre[l-1])*(m/l)*(m/l);
		}ans+=cur;
	}cout<<ans<<'\n';
	return 0;
}

P1891 疯狂 LCM

题目要求:

\[\begin{aligned}\sum_{i=1}^{n}\operatorname{lcm}(i,n)&=n\sum_{i=1}^n\dfrac{i}{\gcd(i,n)}\\&=n\sum_{d|n}\sum_{i=1}^n\dfrac{i}{d}[\gcd(i,n)=d]\\&=n\sum_{d|n}\sum_{i=1}^{\frac{n}{d}}i[\gcd(i,\frac{n}{d})=1]\\&=n\sum_{d|n}\dfrac{\varphi(\frac{n}{d})\times\frac{n}{d}}{2}\\&=n\sum_{d|n}\dfrac{\varphi(d)\times d}{2}\\&=\dfrac{n}{2}\sum_{d|n}\varphi(d)\times d\end{aligned} \]

\(f(x)=\sum\limits_{d|x}\varphi(d)\times d\),这是个积性函数,可以筛出来。

$\texttt{Code}$
const int MAXN=1e6+10;
int p[MAXN],pr[MAXN],cnt;
ll f[MAXN];
void init(){
	f[1]=1;p[1]=1;
	rep(i,2,MAXN-10){
		if(!p[i]){pr[++cnt]=i,f[i]=1ll*i*(i-1)+1;}
		for(int j=1;j<=cnt&&i*pr[j]<=MAXN-10;j++){
			p[i*pr[j]]=1;
			if(i%pr[j]) f[i*pr[j]]=f[i]*f[pr[j]];
			else{f[i*pr[j]]=f[i]+(f[i]-f[i/pr[j]])*pr[j]*pr[j];break;}
		}
	}
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	init();
	int T;for(cin>>T;T--;){
		int n;cin>>n;
		cout<<1ll*(n*f[n]+n)/2<<'\n';
	}
	return 0;
}

SP21615 NAJPWG - Playing with GCD

题目要求:

\[\begin{aligned} \sum_{i=1}^n\sum_{j=i}^n[\gcd(i,j)>1]&=\sum_{i=1}^n\sum_{j=1}^i[\gcd(i,j)\not=1] \\&=\sum_{i=1}^ni-\varphi(i) \end{aligned}\]

直接预处理就好了。

$\texttt{Code}$
const int MAXN=1e5+10;
int p[MAXN],pr[MAXN],phi[MAXN],cnt;
int ans[MAXN];
void init(){
	phi[1]=1;p[1]=1;
	rep(i,2,MAXN-10){
		if(!p[i]) pr[++cnt]=i,phi[i]=i-1;
		for(int j=1;j<=cnt&&i*pr[j]<=MAXN-10;j++){
			p[i*pr[j]]=1;
			if(i%pr[j]) phi[i*pr[j]]=phi[i]*phi[pr[j]];
			else{phi[i*pr[j]]=phi[i]*pr[j];break;}
		}
	}rep(i,1,MAXN-10) ans[i]=ans[i-1]+i-phi[i];
}
void solve(int Cas){
	int n;
	cin>>n;
	cout<<"Case "<<Cas<<": "<<ans[n]<<'\n';
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	init();
	int T;cin>>T;
	rep(_,1,T) solve(_);
	return 0;
}

AT5310 [ABC162E] Sum of gcd of Tuples (Hard)

posted @ 2022-02-27 21:15  ZCETHAN  阅读(88)  评论(0编辑  收藏  举报