莫比乌斯反演

前置知识

数论分块

数论分块,还可以称为整除分块。

可以注意到,对于一个数 \(n\) , \(\lfloor \frac{n}{i}\rfloor\) 呈现一种块状分布,并且对于 \(\lfloor \frac{n}{i}\rfloor\) 的一块来说,最后一个数是\(\lfloor\frac{n}{\lfloor \frac{n}{i}\rfloor}\rfloor\)

证明:

\[\frac{n}{i}=\lfloor\frac{n}{i}\rfloor+r\quad (r<1)\\ \implies \lfloor\frac{n}{\lfloor\frac{n}{i} \rfloor}\rfloor\geq\lfloor\frac{n}{\lfloor\frac{n}{i} \rfloor+r}\rfloor =\lfloor\frac{n}{\frac{n}{i}} \rfloor\\ \implies \lfloor\frac{n}{\lfloor\frac{n}{i} \rfloor}\rfloor\geq i \]

而这时我们就可以一块一块的处理了,而块数数量级为 \(O(\sqrt{n})\) ,证明如下:

  • 对于 \(i\leq\sqrt{n}\) ,就算每个 \(i\) 取值都不同, \(\lfloor \frac{n}{i}\rfloor\) 最多也只有 \(\sqrt{n}\) 种取值。
  • 对于 \(i\geq\sqrt{n}\)\(\lfloor \frac{n}{i}\rfloor\leq\sqrt{n}\) ,自然最多有 \(\sqrt{n}\) 种取值。
  • 所以 \(\lfloor \frac{n}{i}\rfloor\) 的取值有 \(O(\sqrt{n})\) 种。

我们举个例子,求:

\[\sum_{i=1}^{n}k\; mod\;i \]

乍一看和分块没有联系,那么我们化一下:

\[\sum_{i=1}^{n}k-\lfloor\frac{k}{i} \rfloor \]

其中 \(k\) 的区间和是可以 \(O(1)\) 求的,而通过整除分块,我们也可以 \(O(\sqrt{n})\) 求出后面的减项的区间和,这样就吧 \(O(n)\) 的复杂度降到了 \(O(\sqrt{n})\)

积性函数

如果一个函数 \(f\) 有:

\[f(xy)=f(x)\times f(y)\quad if\;x\bot y \]

我们就把 \(f\) 称作积性函数。

常见的积性函数有:

  • \(\varphi\) :欧拉函数
  • \(I\) :不变函数,恒为 \(1\)
  • \(x^a\) :幂函数
  • \(\epsilon\) :单位元,只有 \(\epsilon(1)=1\) ,其它为 \(0\)
  • \(d\) :约数个数函数
  • \(\sigma\) :约数和函数
  • \(\mu\) :莫比乌斯函数,详见下文

这里有一个小结论:

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

如果 \(f\) 是积性函数,那么 \(g\) 也是积性函数。

证明:

\[x\bot y\\ g(x)\times g(y)=\sum_{i|x}f(i)\sum_{j|y}f(j)\\ =\sum_{i|x}\sum_{j|y} f(ij) \\ =\sum_{d|xy}f(d)\\ =g(xy) \]


由于积性函数性质特殊,我们经常需要线性筛来求。

Dirichlet 卷积

定义 \(Dirichlet\) 卷积为:

\[f=g*h\iff f(n)=\sum_{d|n}g(d)h(\frac{n}{d}) \]


卷积满足的定律有:

  • 交换律:

    这里有个小定理:

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

很显然成立,因为 \(n\) 的因数是成对的。

那么就显然:

\[g*h=h*g \]

  • 结合律:

    同样有一个小技巧,对于二重和式:

    \[\sum_{d|n}\sum_{x|d}F(d,x) \]

    我们可以将 \(d=lx\) 代入式中,从而将 \(x\) 换成第一个枚举项:

    \[\sum_{d|n}\sum_{x|d}F(d,x)=\sum_{x|n}\sum_{xl|n}F(lx,x) =\sum_{x|n}\sum_{l|\frac{n}{x}}F(xl,x) \]

    应用到结合律证明中:

    \[(f*g)*h=f*(g*h)\\ \implies \sum_{d|n}\sum_{x|d}f(x)g(\frac{d}{x})h(\frac{n}{d})=\sum_{d|n}\sum_{x|d}f(\frac{n}{d})g(\frac{d}{x})h(x)\\ \implies\sum_{d|n}\sum_{x|d}f(x)h(\frac{n}{d})=\sum_{d|n}\sum_{x|d}f(\frac{n}{d})h(x)\\ \implies \sum_{x|n}\sum_{l|\frac{n}{x}}f(x)h(\frac{n}{lx})=\sum_{d|n}\sum_{x|d}f(\frac{n}{d})h(x)\\ \implies \sum_{x|n}\sum_{l|x}f(\frac{n}{x})h(\frac{x}{l})=\sum_{d|n}\sum_{x|d}f(\frac{n}{d})h(x)\\ \implies \sum_{x|n}\sum_{l|x}f(\frac{n}{x})h(l)=\sum_{d|n}\sum_{x|d}f(\frac{n}{d})h(x) \]

    可以发现只是换了个符号,两式等价。

  • 分配律:

    \[\sum_{d|n}[f(d)+g(d)]h(\frac{n}{d})=\sum_{d|n}f(d)h(\frac{n}{d})+\sum_{d|n}g(d)h(\frac{n}{d}) \]

    显然成立。


常见卷积:

  • \(d=I*I=\sum_{d|n} 1\)

  • \(n=\varphi*I=\sum_{d|n}\varphi(d)\) ,这个卷积被称作 欧拉反演 ,证明如下:

    对于质数的幂次 \(p^k\)

    \[\sum_{d|p^k}\varphi(d)=1+(p-1)+(p^2-p)+\cdots+(p^k-p^{k-1})=p^k \]

    又因为此式是积性函数,所以对于任意的 \(x=p_1^{a_1}p_2^{a_2}\cdots p_r^{a_r}\)

    \[\sum_{d|x}\varphi(d)=\sum_{d|p_1^{a_1}}\varphi(d)\sum_{d|p_2^{a_2}}\varphi(d)\cdots\sum_{d|p_r^{a_r}}\varphi(d)=p_1^{a_1}p_2^{a_2}\cdots p_r^{a_r}=x \]

  • \(\sigma=n*I=\sum_{d|n}d\) ,代入上面那个结论可得:\(\sigma=\varphi*d\)

莫比乌斯函数

莫比乌斯函数 \(\mu\) 如下定义:

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

\([n==1]\) 表示一个 \(bool\) 表达式,为真时返回 \(1\) ,否则返回 \(0\)

卷积表示为 :

\[\epsilon=\mu*I \]

而详细的 \(\mu\) 值为:

\[\mu(x)= \begin{cases} 1 & \text{$x=1$}\\ (-1)^r & \text{$x=p_1p_2\dots p_r$}\\ 0 & \text{else} \end{cases} \]

第二项表示,对 \(x\) 因式分解后,如果质因子都是一次幂,\(\mu\) 值为 \(1\) , 如果有任意一个质因子幂次大于等于 \(2\) ,那么 \(\mu\) 值为 \(0\)

看到这里,大概已经很懵逼 \(\mu\) 如此奇怪的值了,实际上,\(\mu\) 的定义是为了进行反演,所以并不是基于单个值,而是基于卷积,单个值只是解出来的,所以讨论单个值没有意义。

莫比乌斯反演

对于函数:

\[F=f*I\iff F(n)=\sum_{d|n}f(d) \]

莫比乌斯函数可以使得:

\[f=F*\mu\iff f(n)=\sum_{d|n}\mu(\frac{n}{d})F(d) \]


证明:(用到了上面证结合律和交换律的小技巧)

\[\begin{align} \sum_{d|n}\mu(\frac{n}{d})F(d)=\sum_{d|n}\mu(\frac{n}{d})\sum_{x|d}f(x)\\ =\sum_{d|n}\sum_{x|d}\mu(\frac{n}{d})f(x)\\ =\sum_{x|n}\sum_{l|\frac{n}{x}}\mu(\frac{n}{xl})f(x)\\ =\sum_{x|n}f(x)\sum_{l|\frac{n}{x}}\mu(l)\\ =\sum_{x|n}f(x)[\frac{n}{x}==1]\\ =f(n) \end{align} \]

除了 \(d|n\) 型以外,莫比乌斯反演还更常用到 \(n|d\) 的形式:

\[F(n)=\sum_{n|d}f(d)\\ f(n)=\sum_{n|d}\mu(\frac{d}{n})F(d) \]

证明:

\[\begin{align} \sum_{n|d}\mu(\frac{d}{n})F(d)=\sum_{n|d}\sum_{d|x}\mu(\frac{d}{n})f(x)\\ =\sum_{n|d}\sum_{d|x}\mu(\frac{d}{n})f(x)\\ \bf 将\rm d=\frac{x}{k} \bf代入\rm\\ =\sum_{n|x}f(x)\sum_{k|\frac{x}{n}}\mu(\frac{x}{nk})\\ =\sum_{n|x}f(x)\sum_{k|\frac{x}{n}}\mu(k)\\ =\sum_{n|x}f(x)[\frac{x}{n}==1] =f(n) \end{align} \]

当然也可以用卷积定义去证明:

\[F=f*I\implies\mu*F=f*I*\mu\implies F*\mu=f*\epsilon\implies f=F*\mu \]


有了莫比乌斯反演,我们在题目中就可以通过可能较好表示的 \(f\) 的卷积来反推 \(f\)

例题

YY的GCD

题目是让求:

\[\sum_{i=1}^{N}\sum_{j=1}^{M}[\gcd(i,j)==p]\quad p\in prime \]

多组数据,\(T\leq1e4\)\(N,M\leq1e7\)

首先不妨设 \(N\leq M\)

然后我们设 \(f(x)\)\(gcd\)\(x\) 的数的对数 ,\(F(x)\) 是公约数(不是最大公约数)的个数。

显然有:

\[f(n)=\sum_{i=1}^{N}\sum_{j=1}^{M}[\gcd(i,j)==n]\\ F(n)=\sum_{n|d}^{N}f(d)=\lfloor \frac{N}{n}\rfloor\lfloor \frac{M}{n}\rfloor\\ \therefore f(n)=\sum_{n|d}^{N}\mu(\frac{d}{n})F(d) \]

而我们要求的是:

\[\begin{align} \sum_{p}^{N}f(p) =\sum_{p}^{N}\sum_{p|d}^{N}\mu(\frac{d}{p})\lfloor \frac{N}{d}\rfloor\lfloor \frac{M}{d}\rfloor \tag{$p\in prime$} \end{align} \]

如果直接枚举 \(p\) ,后面得一个个算 \(\lfloor \frac{N}{d}\rfloor\),需要 \(O(T\times prime\times\sqrt{N})\) 的复杂度 。是过不了这题的。

我们需要换一个枚举项,好预处理。

我们尝试枚举 \(d\) :

\[\sum_{d=1}^{N}\lfloor \frac{N}{d}\rfloor\lfloor \frac{M}{d}\rfloor\sum_{p|d}\mu(\frac{d}{p}) \]

如此一来前半部分可以数论分块求出。问题就到了后半部分。

我们发现,后半部分竟然可以线性筛出!

我们设 \(h(x)=\sum_{p|x}\mu(\frac{x}{p})\)

  • 对于 \(x\) 是质数的情况,很显然 \(h(x)=\mu(1)=1\)

  • 对于递推情况 \(h(x\times p),\;p\in prime\)

    \(p\) 不是 \(x\) 已有的质因子,原来的 \(\mu\) 项中都会多一个质因子,值取负,再加上新增的一项 \(\mu(x)\)

    \(p\)\(x\) 已有的质因子,但是只有一次幂,那么,除了 \(\mu(\frac{x\times p}{p})\) 的一项外,其他项都变为 \(0\) ,所以值为 \(\mu(x)\)

    \(x\) 中有大于等于二次幂的 \(p\) 因子,值直接为 \(0\)

总结起来就是:

\[h(p)=1\\ h(x\times p)= \begin{cases} \mu(x)-f(x) \qquad x\%p\neq0\\ \mu(x) \qquad x\%p=0\;and\; (x/p)\%p\neq0\\ 0 \qquad else \end{cases} \]

那么线性筛出 \(h\) ,并处理出其前缀和,然后数论分块就可以达到 \(O(N+T\times \sqrt{N})\) 的复杂度了。

\(\frak Code\)

#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 10000000

long long ans;
int n,m,t;
int tot;
int prime[1000050],inp[10000050],mu[10000050],su[10000050],sum[10000050];

void prework(){
	inp[0]=inp[1]=1;
	mu[1]=1;
	su[1]=0;
	sum[0]=sum[1]=0;
	for(int i=2;i<=MAXN;i++){
		if(!inp[i]){
			prime[++tot]=i;
			mu[i]=-1;
			su[i]=mu[1];
		}
		for(int j=1;j <= tot && 1ll*prime[j]*i <= MAXN;j++){
			int tp=prime[j]*i;
			inp[tp]=1;
			if(i%prime[j]==0){
				mu[tp]=0;
				if((i/prime[j])%prime[j] == 0)
					su[tp]=0;
				else
					su[tp]=mu[i];
				
				break;
			}
			su[tp]=mu[i]-su[i];
			mu[tp]=-1*mu[i];
		}
		
		sum[i]=sum[i-1]+su[i];
	}
}


int main()
{
	scanf("%d",&t);
	
	prework();
	
	while(t--){
		ans=0;
		scanf("%d %d",&n,&m);
		if(m<n) swap(n,m); 
		
		for(int i=2;i<=n;i++){
			int lt=min(n,min(n/(n/i),m/(m/i)));
			ans+=1ll*(sum[lt]-sum[i-1])*(n/i)*(m/i);
			i=lt;
		}
		
		printf("%lld\n",ans);
	}
	return 0;
}
 
 

声明及感谢

部分内容参考自:


-EOF-
posted @ 2020-02-24 19:50  T_horn  阅读(257)  评论(0编辑  收藏  举报