莫比乌斯反演

莫比乌斯函数

定义

定义莫比乌斯函数

\[\begin{equation} \mu(x)=\left\{ \begin{aligned} 0& &x有因子为非1的平方数 \\ 1& &x=1 \\ (-1)^k& &x的因子不含非1的平方数,其中 k = x 的质因子个数 \end{aligned} \right. \end{equation} \]

即:在 \(x \neq 1\) 时,对 \(x\) 分解质因数,如果其中有一个质因子的幂次大于等于 \(2\) ,则有 \(\mu(x) = 0\) ;否则,若 \(x\) 有奇数个质因子,则 \(\mu(x) = -1\) ,若 \(x\) 有偶数个质因子,则 \(\mu(x) = 1\)

\(x = 1\) 时,有 \(\mu(x) = 1\)

性质

  1. 莫比乌斯函数是积性函数

    即:对于任意互质的整数 \(a , b\) ,都有 \(\mu(ab)=\mu(a) \mu(b)\) ,利用这个性质,可以利用欧拉筛在 \(\Theta(n)\) 的时间内求出 \(\forall_{i \leq n} \mu(i)\) ,并可用杜教筛快速计算 \(\sum\limits_{i=1}^{n} \mu(i)\)

  2. 莫比乌斯函数 \(\mu\) 在迪利克雷卷积中为常数函数 \(1\) 的逆元。

    即:对任意数论函数 \(f(x)\)\(g(x)\) ,若有 \(f(n)=\sum\limits_{d|n}g(d)\) 则有 \(g(n)=\sum\limits_{d|n}f(d)\mu(\frac{n}{d})\) ,这里数论函数 $g(n) 即为数论函数 \(f(n)\) 的莫比乌斯反演。

重要结论

  1. \(\epsilon(x) = \sum\limits_{d|x} \mu(d)\)

\[\begin{equation} \sum\limits_{d|n}\mu(d)=\left\{ \begin{aligned} 0& &x \neq 1 \\ 1& &x = 1 \\ \end{aligned} \right. \end{equation} \]

证明:由性质 2 可以推出 \(\mu*1=\epsilon\) ,写成迪利克雷卷积即可。

  1. \([\gcd(i,j)=1] = \sum\limits_{d|\gcd(i,j)}\mu(d)\)

    证明:由结论1可得,\(\sum\limits_{d|\gcd(i,j)}\mu(d) = \epsilon(\gcd(i,j))\) ,当且仅当 \(\gcd(i,j) = 1\) 时,其值为 \(\epsilon(1) = 1\)

莫比乌斯函数求值

莫比乌斯反演一般会用到莫比乌斯函数的前缀和,下面提供两种计算方法,各有优劣。

欧拉筛

欧拉筛适用于对积性函数求值,上文提到 \(\mu\) 为积性函数,故可以利用欧拉筛在 \(\Theta(n)\) 的时间内求出 \(\forall_{i \leq n} \mu(i)\)

通过欧拉筛求积性函数的值,需要确定 \(3\) 种情况下函数的取值:\(x\) 为质数、 \(x = y \cdot p\)\(y \mod p \neq 0\)\(x = y \cdot p\)\(y \mod p = 0\) ,其中 \(p\)\(x\) 的最小质因子。

  1. \(x\) 为质数时,根据定义可得 \(\mu(x)=1\)

  2. \(x = y \cdot p\)\(y \mod p \neq 0\) 时,一定有 \(p^2|x\) ,根据定义, \(mu(x)=0\)

  3. \(x = y \cdot p\)\(y \mod p = 0\) 时,若 \(y\) 含有平方因子,则 \(\mu(x)=\mu(y)=0\) ;若 \(y\) 不含平方因子,根据定义可知:\(\mu(x)=-\mu(y)\) 。综上,当 \(y \mod p = 0\) 时, \(\mu(x)=-mu(y)\)

由此可以写出线性时间求解莫比乌斯函数的代码:

inline void Euler(int n) {
	mu[1]=1; //根据定义得
	for(int i=2;i<=n;i++) {
		if(!vis[i]) mu[i]=-1,pr[++pcnt]=i; //情况1:质数
		for(int j=1;j<=pcnt&&i*pr[j]<=n;j++) {
			vis[i*pr[j]]=true;
			if(i%pr[j]==0) {
				mu[i*pr[j]]=0;break; //情况2:相同质因子
			}
			mu[i*pr[j]]=-mu[i]; //情况3:新的不同质因子
		}
	}
}

杜教筛

有时题目要求快速计算 \(\mu(i)\) 的前缀和,即 \(\sum\limits_{i=1}^{n}\mu(i)\) 的值,这时杜教筛可以在低于 \(\Theta(n)\) 的时间内求出前缀和在某个位置上的值。

杜教筛要求找出一个 \(g(x)\) 与当前函数 \(f(x)\) 做迪利克雷卷积,且卷积的前缀和好求,而根据之前提到的性质: \(\mu * 1 = \epsilon\)\(f(x)\) 直接取常数函数 \(1\) 即可。

定义 \(sum(x)=\sum\limits_{i=1}^{x} \mu(i)\)

根据杜教筛的式子 \(g(1)sum(n)=\sum\limits_{i=1}^{n}(f * g)(i) - \sum\limits_{i=2}^{n} g(i)sum(\lfloor \frac{n}{i} \rfloor)\) ,用常数函数 \(1\) 替换 \(g\) ,用 \(\mu\) 替换 \(f\) 可得: \(sum(n)=\sum\limits_{i=1}^{n}\epsilon(i) - \sum\limits_{i=2}^{n} sum(\lfloor \frac{n}{i} \rfloor)\) ,显然, \(\sum\limits_{i=1}^{n}\epsilon(i) = 1\),而\(\sum\limits_{i=2}^{n} sum(\lfloor \frac{n}{i} \rfloor)\) 可用数论分块在加速计算。

直接递归计算的时间复杂度为 \(\Theta(n^{\frac{3}{4}})\) ,如果提前用欧拉筛计算出出前 \(n^{\frac{2}{3}}\) 项的前缀和,则时间复杂度可以降低至 \(\Theta({n^{\frac{2}{3}}})\)

代码:

unordered_map<long long,long long>mp1; //map是O(logn)查询修改,选用unordered_map可以获得更优的O(1)查询修改
long long SumMu(long long n) { //先调用 Euler(MAXN-1) 预处理前 MAXN 项的 sumMu
	if(n<MAXN) return sumM[n]; //如果当前的n在预处理的范围内,就直接返回
	if(mp.find(n)!=mp.end()) return mp[n]; //如果当前的值之前求过,就直接返回
	long long res=1; //epsilon前缀和=1
	for(long long i=2;i<=n;i++) { //数论分块
		int j=n/(n/i);
		res-=1ll*(j-i+1)*SumMu(n/i);
		i=j;
	}
	mp[n]=res; //记忆化加速下次查询
	return res;
}

应用

[POI2007]ZAP-Queries

[POI2007]ZAP-Queries

给出 \(a,b,d\),求 \(\sum\limits_{x=1}^{a}\sum\limits_{y=1}^{b} [\gcd(x,y)=d]\),多组数据。

上文证明 \([\gcd(x,y)=1]=\sum\limits_{d|\gcd(x,y)}\mu(d)\) ,而题目要求 \([\gcd(x,y)=d]\)。考虑将 \(d\) 化成 \(1\) ,用 \(x \cdot d\)\(x\)\(y \cdot d\)\(y\),得到 \(\sum\limits_{x=1}^{\lfloor \frac{a}{d} \rfloor}\sum\limits_{y=1}^{\lfloor \frac{b}{d} \rfloor}[\gcd(x,y)=1]\)

\(f(n,m)=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[\gcd(i,j)=1]\),用莫比乌斯函数替换 \(\gcd(i,j)=1\) 的条件,即有 \(f(n,m)=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}\sum\limits_{k|i,k|j}\mu(k)\)。考虑先枚举 \(k\) ,发现 \(k\) 的范围为 \([1,\min(n,m)]\)\(n \leq m\),即可将上式化为 \(f(n,m)=\sum\limits_{k=1}^{n}\mu(k)\sum\limits_{k|i}^{n}\sum\limits_{k|j}^{m}1\)。由于小于 \(n\)\(k\) 的倍数共有 \(\lfloor\frac{n}{k}\rfloor\) 个,\(m\) 同理,则有 \(f(n,m)=\sum\limits_{k=1}^{n}\mu(k)\lfloor\frac{n}{k}\rfloor\lfloor\frac{n}{k}\rfloor\),预处理出 \(\mu\) 的前缀和后,利用数论分块可在 \(\Theta(\sqrt{n})\) 的时间内计算 \(f(n,m)\)

题目要求的式子就等于 \(f(\lfloor\frac{a}{d}\rfloor,\lfloor\frac{b}{d}\rfloor)\),利用欧拉筛预处理 \(\mu\) 的前缀和,即可实现 \(\Theta(n)\) 预处理, \(O(\sqrt{n})\) 回答一次询问。

回答询问代码:

inline int calc(int n,int m) {
	if(n>m) swap(n,m);
	int res=0;
	for(int i=1;i<=n;i++) { //数论分块
		int j=min(n/(n/i),m/(m/i));
		res+=(sum[j]-sum[i-1])*(n/i)*(m/i); //sum为mu的前缀和
		i=j;
	}
	return res;
}

PGCD - Primes in GCD Table

PGCD - Primes in GCD Table

给定 \(n\)\(m\) ,求 \(1 \leq x \leq n,1 \leq y \leq m\)\(\gcd(x,y)\) 为质数的 \((x,y)\) 有多少对,至多 \(10\) 次询问。

即是求: \(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[\gcd(n,m) \in Prime]\)。莫比乌斯反演套路:先枚举 \(\gcd(i,j)\) 的值,可将原式化为 \(\sum\limits_{g \in Prime}\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[\gcd(i,j)=g]\) ,继续用上一题的套路,将 \(g\) 化为 \(1\),得到 \(\sum\limits_{g \in Prime}\sum\limits_{i=1}^{\lfloor \frac{n}{g}\rfloor}\sum\limits_{j=1}^{\lfloor \frac{m}{g} \rfloor}[\gcd(i,j)=1]\),转化 \(\gcd(i,j)=1\) 的条件得到:\(\sum\limits_{g \in Prime}\sum\limits_{i=1}^{\lfloor \frac{n}{g}\rfloor}\sum\limits_{j=1}^{\lfloor \frac{m}{g} \rfloor}\sum\limits_{d|i,d|j}\mu(d)\)。和上一题一样,令 \(f(n,m)=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[\gcd(i,j)=1]\),则有 \(f(n,m)=\sum\limits_{k=1}^{n}\mu(k)\lfloor\frac{n}{k}\rfloor\lfloor\frac{n}{k}\rfloor\),即可将原式化为 \(\sum\limits_{g \in Prime} f(\lfloor \frac{n}{g} \rfloor,\lfloor \frac{m}{g} \rfloor)\) ,令 \(g(x)=[x \in Prime]\),显然,\(g\) 的前缀和可以在筛出质数后 \(\Theta(n)\) 预处理,则可以将原式化为 \(\sum\limits_{i=1}^{n} g(i) f(\lfloor \frac{n}{g} \rfloor,\lfloor \frac{m}{g} \rfloor)\),用数论分块求解即可。

这里是两层数论分块的嵌套,回答一次询问的时间复杂度为 \(\Theta(n^{\frac{3}{4}})\) ,本题询问量不大,可以通过。

回答询问代码:

inline long long f(int n,int m) { //数论分块求f(n,m)
	if(n>m) swap(n,m);
	long long res=0;
	for(int i=1;i<=n;i++) {
		int j=min(n/(n/i),m/(m/i));
		res+=1ll*(smu[j]-smu[i-1])*(n/i)*(m/i);
		i=j;
	}
	return res;
}
inline long long calc(int n,int m) {
	if(n>m) swap(n,m);
	long long res=0;
	for(int i=1;i<=n;i++) {
		int j=min(n/(n/i),m/(m/i));
		res+=1ll*(spr[j]-spr[i-1])*f(n/i,m/i); //spr为g的前缀和
		i=j;
	}
	return res;
}

YY的GCD

YY的GCD

给定 \(n\)\(m\) ,求 \(1 \leq x \leq n,1 \leq y \leq m\)\(\gcd(x,y)\) 为质数的 \((x,y)\) 有多少对,至多 \(10^4\) 次询问。

随着询问次数的增加,上一题的方法已经无法通过,考虑优化。

拆开 \(f\) 得到:\(\sum\limits_{i=1}^{n} g(i) \sum\limits_{j=1}^{\lfloor \frac{n}{i} \rfloor} \lfloor \frac{n}{ij} \rfloor \lfloor \frac{m}{ij} \rfloor \mu(j)\),令 \(k=i \cdot j\),则原式化为 \(\sum\limits_{i=1}^{n} g(i) \sum\limits_{j=1}^{\lfloor \frac{n}{i} \rfloor} \lfloor \frac{n}{k} \rfloor \lfloor \frac{m}{k} \rfloor \mu(\frac{k}{i})\) ,变换枚举顺序,先枚举 \(k\) ,得到 \(\sum\limits_{k=1}^{n}\sum\limits_{i|k}g(i)\mu( \frac{k}{i}) \lfloor\frac{n}{k}\rfloor \lfloor\frac{m}{k}\rfloor\)。可以发现,最后两项与 \(i\) 无关,可以提到前面,得到 \(\sum\limits_{k=1}^{n}\lfloor\frac{n}{k}\rfloor \lfloor\frac{m}{k}\rfloor\sum\limits_{i|k}g(i)\mu(\frac{k}{i})\)。令 \(h(x)=\sum\limits{i|x}g(i)\mu(\frac{k}{i})\),即有 \(h(x)=\sum\limits_{i \in Prime,i|x}\mu(\frac{i}{i})\)。推导至此,即可在欧拉筛后枚举每个质数的倍数计算 \(h(x)\) 的值,认为质数个数约为 \(\frac{n}{\ln n}\) 时,计算 \(h(x)\) 的时间复杂度约为为 \(\Theta(n)\),可以通过。

关键代码:

inline void init(int n) {
	Euler(n); //欧拉筛质数和mu
	for(int i=1;i<=pcnt;i++) { //枚举质数求h的值
		for(int j=1;pr[i]*j<=n;j++) {
			sum[pr[i]*j]+=mu[j];
		}
	}
	for(int i=1;i<=n;i++) {
		smu[i]=smu[i-1]+mu[i];
		sum[i]+=sum[i-1];
	}
}
inline long long calc(int n,int m) {
	if(n>m) swap(n,m);
	long long res=0;
	for(int i=1;i<=n;i++) { //数论分块
		int j=min(n/(n/i),m/(m/i));
		res+=1ll*(sum[j]-sum[i-1])*(n/i)*(m/i);
		i=j;
	}
	return res;
}

当然,\(h(x)\)的值也可用欧拉筛在线性时间内筛出.

和之前考虑欧拉筛 \(\mu\) 一样,仍然考虑欧拉筛会遇到的三种情况:\(x\) 为质数、 \(x = y \cdot p\)\(y \mod p \neq 0\)\(x = y \cdot p\)\(y \mod p = 0\) ,其中 \(p\)\(x\) 的最小质因子。

  1. \(x\) 为质数时,由于 \(1\) 不是质数,故只会枚举到 \(i=x\) 的情况,即当 \(x\) 为质数时, \(h(x)=\mu(\frac{x}{x})=\mu(1)=1\)

  2. \(x = y \cdot p\)\(y \mod p \neq 0\) 时,\(p\)\(x\) 相比于 \(y\) 多出的一个新的质因子,这会导致 \(h(y)\) 中枚举到的 \(\frac{y}{i}\) 变成 \(\frac{yp}{i}\),根据 \(\mu\) 的定义得出 \(\mu(\frac{yp}{i})=-mu(\frac{y}{i})\),则有\(\mu(\frac{x}{i})=-mu(\frac{y}{i})\)。再考虑由于 \(p\) 而多出来的部分,因为枚举到的 \(i\) 为质数,故只会多枚举一个 \(p\),则只会多贡献一个 \(\mu(\frac{x}{p})=\mu(y)\)。 由此得出:当 \(x = y \cdot p\)\(y \mod p \neq 0\) 时, \(h(x)=-h(y)+\mu(p)\)

  3. \(x = y \cdot p\)\(y \mod p = 0\) 时,\(p\)\(x\) 的一个幂次大于等于 \(2\) 的质因子,根据 \(\mu\) 定义,由于枚举到的 \(i\) 均为质数,故当 \(i \neq p\) 时,所有的 \(\mu(\frac{x}{i})=0\)。最后剩下一个新枚举到的 \(p\) ,对结果的贡献为 \(\mu(\frac{x}{p})=\mu(y)\)。由此得出:当 \(x = y \cdot p\)\(y \mod p = 0\) 时, \(h(x)=\mu(y)\)

据此可以利用欧拉筛在 \(\Theta(n)\) 的时间内求解 \(h(x)\) 的值和前缀和,略快于上一个做法。

关键代码:

inline void Euler(int n) {
	mu[1]=1;f[1]=0; //根据定义得到
	for(int i=2;i<=n;i++) {
		if(!vis[i]) mu[i]=-1,pr[++pcnt]=i,f[i]=1; //情况1
		for(int j=1;j<=pcnt&&i*pr[j]<=n;j++) {
			vis[i*pr[j]]=true;
			if(i%pr[j]==0) {
				mu[i*pr[j]]=0;
				f[i*pr[j]]=mu[i];break; //情况2
			}
			mu[i*pr[j]]=-mu[i];
			f[i*pr[j]]=-f[i]+mu[i]; //情况3
		}
	}
	for(int i=1;i<=n;i++) sum[i]=sum[i-1]+f[i];
}
inline long long calc(int n,int m) {
	if(n>m) swap(n,m);
	long long res=0;
	for(int i=1;i<=n;i++) { //数论分块
		int j=min(n/(n/i),m/(m/i));
		res+=(sum[j]-sum[i-1])*(n/i)*(m/i);
		i=j;
	}
	return res;
}

To be continued...

posted @ 2023-03-13 00:08  xzm111  阅读(54)  评论(0)    收藏  举报