莫比乌斯反演

莫比乌斯反演


应该比较清晰易懂吧(雾

莫比乌斯函数

定义

x = p 1 α 1 p 2 α 2 … p k α k , 其 中 p i 是 质 数 , α i 是 正 整 数 x=p_1^{\alpha_1}p_2^{\alpha_2}\dots p_k^{\alpha_k} ,其中p_i是质数,\alpha_i是正整数 x=p1α1p2α2pkαk,pi,αi
μ ( x ) = { c a s e 1 : 存 在 α i ≥ 2 , 此 时 μ ( x ) = 0. c a s e 2 : 所 有 的 α i = 1 , 此 时 μ ( x ) = ( − 1 ) k . 例 : μ ( 6 ) = 1 , μ ( 7 ) = − 1 , μ ( 8 ) = 0. \mu(x)=\begin{cases} case1: 存在\alpha_i \geq2 ,此时\mu(x)=0.\\ case2: 所有的\alpha_i=1,此时\mu(x)=(-1)^k.\\ \end{cases} 例:\mu(6)=1,\mu(7)=-1,\mu(8)=0. μ(x)={case1:αi2,μ(x)=0.case2:αi=1,μ(x)=(1)k.:μ(6)=1,μ(7)=1,μ(8)=0.

s(n)

s ( n ) = ∑ d ∣ n μ ( d ) s(n)=\sum_{d|n}\mu(d) s(n)=dnμ(d)

即n的所有约数的莫比乌斯函数值之和

有:
s ( n ) = { 1 , n = 1. 0 , n > 1. s(n)=\begin{cases} 1,n=1.\\ 0,n>1.\\ \end{cases} s(n)={1,n=1.0,n>1.

反演

F ( n ) = ∑ d ∣ n f ( d ) , 则 f ( n ) = ∑ d ∣ n μ ( d ) F ( n d ) F(n)=\sum_{d|n}f(d),则f(n)=\sum_{d|n}\mu(d)F(\frac{n}{d}) F(n)=dnf(d),f(n)=dnμ(d)F(dn)

简而言之,就是如果我们已知F函数,我们通过套公式可以求出f

因此在某些情况下F函数很好求,我们就可以通过反演求出f

后面的例题就是要靠我们找出哪个是F(n),哪个是f(n),然后把难求的转化成好求的

推导:

∑ d ∣ n μ ( d ) F ( n d ) = ∑ d ∣ n μ ( d ) ∑ i ∣ n d f ( i ) = ∑ i ∣ n f ( i ) ∑ d ∣ n i μ ( d ) \sum_{d|n}\mu(d)F(\frac{n}{d})=\sum_{d|n}\mu(d)\sum_{i|\frac{n}{d}}f(i)=\sum_{i|n}f(i)\sum_{d|\frac{n}{i}}\mu(d) dnμ(d)F(dn)=dnμ(d)idnf(i)=inf(i)dinμ(d)

其中: ∑ d ∣ n i μ ( d ) = s ( n i ) \sum_{d|\frac{n}{i}}\mu(d)=s(\frac{n}{i}) dinμ(d)=s(in)

n = i 时 , 原 式 = f ( n ) , i < n 时 原 式 = 0 n=i时,原式=f(n),i<n时原式=0 n=i,=f(n),i<n=0

一般情况下,我们经常用这个式子(枚举n的倍数):

F ( n ) = ∑ n ∣ d f ( d ) F(n)=\sum_{n|d}f(d) F(n)=ndf(d),则 f ( n ) = ∑ n ∣ d μ ( d n ) F ( d ) f(n)=\sum_{n|d}\mu(\frac{d}{n})F(d) f(n)=ndμ(nd)F(d)

例题

[HAOI2011]Problem b

显然容斥

在这里插入图片描述

S = S b , d − S a − 1 , d − S b , c − 1 + S a − 1 , c − 1 S=S_{b,d}-S_{a-1,d}-S_{b,c-1}+S_{a-1,c-1} S=Sb,dSa1,dSb,c1+Sa1,c1

接着我们考虑怎么定义 F ( n ) , f ( n ) F(n),f(n) F(n),f(n),使得 F ( n ) F(n) F(n)尽量好求

在本题中,我们定义 F ( n ) = ∑ x = 1 a ∑ y = 1 b [ n ∣ g c d ( x , y ) ] F(n)=\sum^a_{x=1}\sum^b_{y=1}[n|gcd(x,y)] F(n)=x=1ay=1b[ngcd(x,y)]

这里的 [ …   ] [\dots] []表示一个条件,满足是1,不满足是0

翻译一下: F ( n ) F(n) F(n)表示在 a , b a,b a,b范围内的点对 ( x , y ) (x,y) (x,y) g c d gcd gcdn的倍数的点的数量

我们定义 f ( n ) = ∑ x = 1 a ∑ y = 1 b [ n = = g c d ( x , y ) ] f(n)=\sum^a_{x=1}\sum^b_{y=1}[n==gcd(x,y)] f(n)=x=1ay=1b[n==gcd(x,y)]

gcd刚好等于n

本题中 F ( n ) = ∑ n ∣ d f ( d ) F(n)=\sum_{n|d}f(d) F(n)=ndf(d),满足上面的式子

因此 f ( n ) = ∑ n ∣ d μ ( d n ) F ( d ) f(n)=\sum_{n|d} \mu(\frac{d}{n})F(d) f(n)=ndμ(nd)F(d)

那么我们怎么求出 F ( d ) F(d) F(d)呢?(d和n这个字母先混用,d好像有歧义,不过问题不大)

d ∣ g c d ( x , y ) d|gcd(x,y) dgcd(x,y)可知 d ∣ x d|x dx d ∣ y d|y dy

a,b范围内,我们有 ⌊ a d ⌋ \lfloor\frac{a}{d}\rfloor da个横坐标是d的倍数, ⌊ b d ⌋ \lfloor\frac{b}{d}\rfloor db个纵坐标是d的倍数

因此 F ( d ) = ⌊ a d ⌋ × ⌊ b d ⌋ F(d)=\lfloor\frac{a}{d}\rfloor\times\lfloor\frac{b}{d}\rfloor F(d)=da×db

f ( n ) = ∑ n ∣ d μ ( d n ) ⌊ a d ⌋ ⌊ b d ⌋ f(n)=\sum_{n|d} \mu(\frac{d}{n})\lfloor\frac{a}{d}\rfloor\lfloor\frac{b}{d}\rfloor f(n)=ndμ(nd)dadb

我们用d'表示 d n \frac{d}{n} nd,那么d'的取值就是1,2,3,4...

那么 f ( n ) = ∑ d ′ μ ( d ′ ) ⌊ a d ′ n ⌋ ⌊ b d ′ n ⌋ f(n)=\sum_{d'}\mu(d')\lfloor\frac{a}{d'n}\rfloor\lfloor\frac{b}{d'n}\rfloor f(n)=dμ(d)dnadnb

再用a',b'表示 a n , b n \frac{a}{n},\frac{b}{n} na,nb

整理得: f ( n ) = ∑ d ′ μ ( d ′ ) ⌊ a ′ d ′ ⌋ ⌊ b ′ d ′ ⌋ f(n)=\sum_{d'}\mu(d')\lfloor\frac{a'}{d'}\rfloor\lfloor\frac{b'}{d'}\rfloor f(n)=dμ(d)dadb

不难发现分子;是定值,而分母的取值是1,2,3,4...,因此分数下取整有 2 n 2\sqrt{n} 2n 种取值,证明就不写了

关于整数分块:

虽然 ⌊ k x ⌋ \lfloor\frac{k}{x}\rfloor xk,有k个取值,但共有 2 n 2\sqrt{n} 2n 种取值

在这里插入图片描述

可以发现k取不同的值时分数值为相通,连续的一段

对于一个x我么如何求出是的分数值与该取值相等的最大取值呢?(问号所指处)

一般我们把这个取值叫 g ( x ) g(x) g(x)

g ( x ) = ⌊ k ⌊ k x ⌋ ⌋ g(x)=\lfloor\frac{k}{\lfloor\frac{k}{x}\rfloor}\rfloor g(x)=xkk,就是k/(k/x)

在这里插入图片描述

回到本题中,我们把a',b'分块,其中蓝色的重合部分,分数取值是相同的

其中c可以带入算, μ \mu μ可以预处理前缀和计算

然后每一段进行这种计算,就OK
Code:

/*************************************************************************
    > File Name: [HAOI2011]Problemb.cpp
    > Author: typedef
    > Mail: 1815979752@qq.com 
    > Created Time: 2021/2/20 7:25:55
 ************************************************************************/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=50010;
int primes[N],cnt,mu[N],sum[N];
bool st[N];
void init(){
	mu[1]=1;
	for(int i=2;i<N;i++){
		if(!st[i]) primes[cnt++]=i,mu[i]=-1;
		for(int j=0;primes[j]*i<N;j++){
			st[primes[j]*i]=1;
			if(i%primes[j]==0) break;
			mu[primes[j]*i]=-mu[i];
		}
	}
	for(int i=1;i<N;i++) sum[i]=sum[i-1]+mu[i];
	return;
}
int g(int k,int x){
	return k/(k/x);
}
ll f(int a,int b,int k){
	a=a/k,b=b/k;
	ll res=0;
	int n=min(a,b);
	for(int l=1,r;l<=n;l=r+1){
		r=min(n,min(g(a,l),g(b,l)));
		res+=(ll)(sum[r]-sum[l-1])*(a/l)*(b/l);
	}
	return res;
}
int main(){
	init();
	int T;
	scanf("%d",&T);
	while(T--){
		int a,b,c,d,k;
		scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
		printf("%lld\n",f(b,d,k)-f(a-1,d,k)-f(b,c-1,k)+f(a-1,c-1,k));
	}
	system("pause");
	return 0;
}

[SDOI2015]约数个数和

题目描述:设 d ( x ) d(x) d(x)x的的约数个数,给定N,M

∑ i = 1 N ∑ j = 1 M d ( i j ) \sum_{i=1}^{N}\sum_{j=1}^{M}d(ij) i=1Nj=1Md(ij)

转化一下:

d ( i j ) = ∑ x ∣ i ∑ y ∣ j [ g c d ( x , y ) = = 1 ] d(ij)=\sum_{x|i}\sum_{y|j}[gcd(x,y)==1] d(ij)=xiyj[gcd(x,y)==1]

原式= ∑ i = 1 N ∑ j = 1 M ∑ x ∣ i ∑ y ∣ j [ g c d ( x , y ) = = 1 ] \sum_{i=1}^{N}\sum_{j=1}^{M}\sum_{x|i}\sum_{y|j}[gcd(x,y)==1] i=1Nj=1Mxiyj[gcd(x,y)==1]

F ( n ) = ∑ i = 1 N ∑ j = 1 M ∑ x ∣ i ∑ y ∣ j [ n ∣ g c d ( x , y ) ] F(n)=\sum_{i=1}^{N}\sum_{j=1}^{M}\sum_{x|i}\sum_{y|j}[n|gcd(x,y)] F(n)=i=1Nj=1Mxiyj[ngcd(x,y)]

f ( n ) = ∑ i = 1 N ∑ j = 1 M ∑ x ∣ i ∑ y ∣ j [ g c d ( x , y ) = = n ] f(n)=\sum_{i=1}^{N}\sum_{j=1}^{M}\sum_{x|i}\sum_{y|j}[gcd(x,y)==n] f(n)=i=1Nj=1Mxiyj[gcd(x,y)==n]

F ( n ) = ∑ n ∣ d f ( n ) F(n)=\sum_{n|d}f(n) F(n)=ndf(n),得 f ( n ) = ∑ n ∣ d μ ( d n ) F ( d ) f(n)=\sum_{n|d}\mu(\frac{d}{n})F(d) f(n)=ndμ(nd)F(d)

f ( 1 ) = ∑ d = 1 N μ ( d ) F ( d ) f(1)=\sum_{d=1}^{N}\mu(d)F(d) f(1)=d=1Nμ(d)F(d)即为所求

那么怎么求 F ( d ) F(d) F(d)呢?

交换一下 ∑ \sum

F ( n ) = ∑ x = 1 N ∑ y = 1 M ⌊ N x ⌋ ⌊ M y ⌋ [ n ∣ g c d ( x , y ) ] F(n)=\sum_{x=1}^{N}\sum_{y=1}^{M}\lfloor\frac{N}{x}\rfloor\lfloor\frac{M}{y}\rfloor[n|gcd(x,y)] F(n)=x=1Ny=1MxNyM[ngcd(x,y)]

x'表示 x n \frac{x}{n} nx,y'表示 y n \frac{y}{n} ny

带入得 F ( n ) = ∑ x ′ = 1 N n ∑ y ′ = 1 M n ⌊ N n x ′ ⌋ ⌊ M n y ′ ⌋ F(n)=\sum_{x'=1}^{\frac{N}{n}}\sum_{y'=1}^{\frac{M}{n}}\lfloor\frac{N}{nx'}\rfloor\lfloor\frac{M}{ny'}\rfloor F(n)=x=1nNy=1nMnxNnyM

再令N',M'表示 N n \frac{N}{n} nN M n \frac{M}{n} nM

F ( n ) = ∑ x ′ = 1 N ′ ∑ y ′ = 1 M ′ ⌊ N ′ x ′ ⌋ ⌊ M ′ y ′ ⌋ = ( ∑ x ′ = 1 N ′ ⌊ N ′ x ′ ⌋ ) ( ∑ y ′ = 1 M ′ ⌊ M ′ y ′ ⌋ ) F(n)=\sum_{x'=1}^{N'}\sum_{y'=1}^{M'}\lfloor\frac{N'}{x'}\rfloor\lfloor\frac{M'}{y'}\rfloor=(\sum_{x'=1}^{N'}\lfloor\frac{N'}{x'}\rfloor)(\sum_{y'=1}^{M'}\lfloor\frac{M'}{y'}\rfloor) F(n)=x=1Ny=1MxNyM=(x=1NxN)(y=1MyM)

括号内两式形式一样,均为: h ( k ) = ∑ i = 1 k ⌊ k i ⌋ h(k)=\sum_{i=1}^{k}\lfloor\frac{k}{i}\rfloor h(k)=i=1kik

因此 F ( n ) = h ( N ′ ) h ( M ′ ) F(n)=h(N')h(M') F(n)=h(N)h(M)

f ( 1 ) = ∑ d = 1 N μ ( d ) h ( N d ) h ( M d ) f(1)=\sum_{d=1}^{N}\mu(d)h(\frac{N}{d})h(\frac{M}{d}) f(1)=d=1Nμ(d)h(dN)h(dM)

我么可以先预处理出 h ( x ) h(x) h(x),使用整数分块,求出段的端点和段的值,从而求出和

回到 f ( 1 ) f(1) f(1)中,我们需要再套一次整数分块,就能够求出结果

Code

/*************************************************************************
    > File Name: [SDOI2015]约数个数.cpp
    > Author: typedef
    > Mail: 1815979752@qq.com 
    > Created Time: 2021/2/20 11:21:29
 ************************************************************************/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=50010;
int primes[N],cnt,mu[N],sum[N],h[N];
bool st[N];
int g(int k,int x){
	return k/(k/x);
}
void init(){
	mu[1]=1;
	for(int i=2;i<N;i++){
		if(!st[i]) primes[cnt++]=i,mu[i]=-1;
		for(int j=0;primes[j]*i<N;j++){
			st[primes[j]*i]=1;
			if(i%primes[j]==0) break;
			mu[i*primes[j]]=-mu[i];
		}
	}
	for(int i=1;i<N;i++) sum[i]=sum[i-1]+mu[i];
	for(int i=1;i<N;i++){
		for(int l=1,r;l<=i;l=r+1){
			r=min(i,g(i,l));
			h[i]+=(r-l+1)*(i/l);
		}
	}
	return;
}
int main(){
	init();
	int T;
	scanf("%d",&T);
	while(T--){
		int n,m;
		scanf("%d%d",&n,&m);
		ll res=0;
		int k=min(m,n);
		for(int l=1,r;l<=k;l=r+1){
			r=min(k,min(g(n,l),g(m,l)));
			res+=(ll)(sum[r]-sum[l-1])*h[n/l]*h[m/l];
		}
		printf("%lld\n",res);
	}
	system("pause");
	return 0;
}
posted @ 2021-02-19 20:18  actypedef  阅读(34)  评论(0编辑  收藏  举报