版权声明:Powered By Fighter https://blog.csdn.net/qq_30115697/article/details/89219146
首先声明,由于我太菜了,本文很多式子可能并不会有详细的证明。若要了解莫比乌斯反演最基本的证明,可以去这里 ,本文主要讲解一些套路。
莫比乌斯函数
我们定义莫比乌斯函数如下:
设
n
=
∏
i
=
1
m
p
i
a
i
,
k
=
∏
i
=
1
m
a
i
μ
(
n
)
=
{
1
(
n
=
1
)
(
−
1
)
m
(
k
=
1
)
0
(
k
>
1
)
设n=\prod_{i=1}^{m} p_i^{a_i},k=\prod_{i=1}^{m} a_i \\ \mu(n)= \begin{cases} 1 & (n=1) \\ (-1)^{m} & (k=1) \\ 0 & (k>1) \end{cases}
设 n = i = 1 ∏ m p i a i , k = i = 1 ∏ m a i μ ( n ) = ⎩ ⎪ ⎨ ⎪ ⎧ 1 ( − 1 ) m 0 ( n = 1 ) ( k = 1 ) ( k > 1 ) 然后我们会发现它是一个积性函数,可以用线性筛
O
(
n
)
O(n)
O ( n ) 求出
1
−
n
1-n
1 − n 的莫比乌斯函数。代码如下:
mu[ 1 ] = 1 ;
for ( int i = 2 ; i <= n; i++ ) {
if ( ! mark[ i] ) {
p[ ++ cnt] = i;
mu[ i] = - 1 ;
}
for ( int j = 1 ; j <= cnt && p[ j] * i <= n; j++ ) {
mark[ p[ j] * i] = 1 ;
if ( i% p[ j] == 0 ) break ;
mu[ i* p[ j] ] = - mu[ i] ;
}
}
同时,莫比乌斯函数还满足:
∑
i
=
1
n
μ
(
i
)
=
[
n
=
1
]
\sum_{i=1}^{n}\mu(i)=[n=1]
i = 1 ∑ n μ ( i ) = [ n = 1 ] 这也是一个美妙的性质(可惜我不会证)。
莫比乌斯反演
依然直接扔公式(是的,我也不会证):
若函数
f
(
n
)
f(n)
f ( n ) 和
g
(
n
)
g(n)
g ( n ) 是数论函数,且满足:
g
(
n
)
=
∑
d
∣
n
f
(
d
)
g(n)=\sum_{d|n}f(d)
g ( n ) = d ∣ n ∑ f ( d ) 那么有如下结论:
f
(
n
)
=
∑
d
∣
n
g
(
d
)
×
μ
(
n
d
)
f(n)=\sum_{d|n}g(d)\times \mu(\frac{n}{d})
f ( n ) = d ∣ n ∑ g ( d ) × μ ( d n ) 实际上,在做题过程中也会遇到上述式子中的
d
∣
n
d|n
d ∣ n 变为
n
∣
d
n|d
n ∣ d ,式子依然成立,但此时
d
d
d 往往有明确的上限。
经典套路
以下默认
n
≤
m
n\leq m
n ≤ m 。
1.求(i,j)=x的个数
这是莫比乌斯反演最经典的应用。
给定
n
,
m
n,m
n , m ,求
f
(
x
)
=
∑
i
=
1
n
∑
j
=
1
m
[
(
i
,
j
)
=
x
]
f(x)=\sum\limits_{i=1}^{n} \sum\limits_{j=1}^{m}[(i,j)=x]
f ( x ) = i = 1 ∑ n j = 1 ∑ m [ ( i , j ) = x ] 。
我们设
g
(
x
)
=
∑
i
=
1
n
∑
j
=
1
m
[
x
∣
(
i
,
j
)
]
g(x)=\sum\limits_{i=1}^{n} \sum\limits_{j=1}^{m}[x|(i,j)]
g ( x ) = i = 1 ∑ n j = 1 ∑ m [ x ∣ ( i , j ) ] 。那么我们发现显然
g
(
x
)
=
∑
x
∣
d
f
(
d
)
g(x)=\sum\limits_{x|d}f(d)
g ( x ) = x ∣ d ∑ f ( d ) 。此处
d
d
d 的上限为
n
n
n 。
于是我们套公式,直接反演一波:
f
(
x
)
=
∑
x
∣
d
g
(
d
)
×
μ
(
d
x
)
。
f(x) = \sum_{x|d}g(d)\times \mu(\frac{d}{x})。
f ( x ) = x ∣ d ∑ g ( d ) × μ ( x d ) 。 我们为啥这么麻烦的反演呢?当然是因为
g
(
x
)
g(x)
g ( x ) 比较好求。我们观察
x
∣
(
i
,
j
)
x|(i,j)
x ∣ ( i , j ) 这个条件,发现
i
,
j
i,j
i , j 均可以表示成
x
×
k
x\times k
x × k ,于是在
n
n
n 和
m
m
m 的范围内,
g
(
x
)
=
⌊
n
x
⌋
×
⌊
m
x
⌋
g(x)=\lfloor \frac{n}{x} \rfloor \times \lfloor \frac{m}{x} \rfloor
g ( x ) = ⌊ x n ⌋ × ⌊ x m ⌋ 。
于是
f
(
x
)
=
∑
x
∣
d
⌊
n
d
⌋
×
⌊
m
d
⌋
×
μ
(
d
x
)
f(x)=\sum\limits_{x|d}\lfloor \frac{n}{d} \rfloor \times \lfloor \frac{m}{d} \rfloor \times \mu(\frac{d}{x})
f ( x ) = x ∣ d ∑ ⌊ d n ⌋ × ⌊ d m ⌋ × μ ( x d ) 。
扫描二维码关注公众号,回复:
5973911 查看本文章
接下来由于
x
∣
d
x|d
x ∣ d 不方便枚举,所以我们设
d
=
t
×
x
d=t \times x
d = t × x ,则
f
(
x
)
=
∑
t
=
1
⌊
n
x
⌋
⌊
n
t
x
⌋
×
⌊
m
t
x
⌋
×
μ
(
t
)
f(x)=\sum\limits_{t=1}^{\lfloor \frac{n}{x}\rfloor} \lfloor \frac{n}{tx} \rfloor \times \lfloor \frac{m}{tx} \rfloor \times \mu(t)
f ( x ) = t = 1 ∑ ⌊ x n ⌋ ⌊ t x n ⌋ × ⌊ t x m ⌋ × μ ( t ) 。
提前处理使
n
=
⌊
n
x
⌋
n=\lfloor \frac{n}{x} \rfloor
n = ⌊ x n ⌋ ,
m
=
⌊
m
x
⌋
m=\lfloor \frac{m}{x} \rfloor
m = ⌊ x m ⌋ ,
f
(
x
)
=
∑
t
=
1
n
⌊
n
t
⌋
×
⌊
m
t
⌋
×
μ
(
t
)
f(x)=\sum\limits_{t=1}^{n}\lfloor \frac{n}{t} \rfloor \times \lfloor \frac{m}{t} \rfloor \times \mu(t)
f ( x ) = t = 1 ∑ n ⌊ t n ⌋ × ⌊ t m ⌋ × μ ( t ) 。
那么我们就可以愉快地
O
(
n
)
O(n)
O ( n ) 求出所有的
f
f
f 函数值了。
但对于多组数据,
O
(
n
)
O(n)
O ( n ) 复杂度显然是不够的,于是我们再用除法分块进行优化。由于此处有
n
n
n 和
m
m
m 两个除法,所以在求除法分块的右边界时需要取最小值,保证两个除法结果均为连续相同的。同时我们对莫比乌斯函数做前缀和,一次分块的答案就是
(
s
u
m
[
r
]
−
s
u
m
[
l
−
1
]
)
×
⌊
n
l
⌋
×
⌊
n
l
⌋
(sum[r]-sum[l-1])\times \lfloor\frac{n}{l}\rfloor \times \lfloor\frac{n}{l}\rfloor
( s u m [ r ] − s u m [ l − 1 ] ) × ⌊ l n ⌋ × ⌊ l n ⌋ ,这样可以做到
O
(
n
)
O(\sqrt n)
O ( n
) 回答。
例题:P4450 双亲数 ,P3455 ZAP-Queries (都是板子题)。
小小的拓展(加个简单容斥):P2522 Problem b 。
代码:
void init ( int n) {
mu[ 1 ] = 1 ;
for ( int i = 2 ; i <= n; i++ ) {
if ( ! mark[ i] ) {
p[ ++ cnt] = i;
mu[ i] = - 1 ;
}
for ( int j = 1 ; j <= cnt && p[ j] * i <= n; j++ ) {
mark[ i* p[ j] ] = true ;
if ( i% p[ j] == 0 ) break ;
mu[ i* p[ j] ] = - mu[ i] ;
}
}
for ( int i = 2 ; i <= n; i++ ) {
mu[ i] + = mu[ i- 1 ] ;
}
}
ll solve ( ll n, ll m) {
if ( n > m) swap ( n, m) ;
ll ans = 0 ;
n / = k, m / = k;
for ( int l = 1 , r; l <= n; l = r+ 1 ) {
r = min ( n/ ( n/ l) , m/ ( m/ l) ) ;
ans + = ( mu[ r] - mu[ l- 1 ] ) * ( n/ l) * ( m/ l) ;
}
return ans;
}
2.求(i,j)为质数的个数
给定
n
,
m
n,m
n , m ,求
f
(
x
)
=
∑
i
=
1
n
∑
j
=
1
m
[
(
i
,
j
)
∈
p
r
i
m
e
]
f(x)=\sum\limits_{i=1}^{n} \sum\limits_{j=1}^{m}[(i,j) \in prime]
f ( x ) = i = 1 ∑ n j = 1 ∑ m [ ( i , j ) ∈ p r i m e ] 。
题面与上面几乎一致,但是推式子难度更大,且需要结合上面的结论。
以下默认
p
∈
p
r
i
m
e
p \in prime
p ∈ p r i m e
f
(
x
)
=
∑
p
∑
i
=
1
n
∑
j
=
1
m
[
(
i
,
j
)
=
p
]
=
∑
p
∑
t
=
1
⌊
n
p
⌋
⌊
n
t
p
⌋
×
⌊
m
t
p
⌋
×
μ
(
t
)
\begin {aligned} f(x) &= \sum_{p}\sum\limits_{i=1}^{n} \sum\limits_{j=1}^{m}[(i,j)=p]\\ &= \sum_{p}\sum\limits_{t=1}^{\lfloor \frac{n}{p}\rfloor} \lfloor \frac{n}{tp} \rfloor \times \lfloor \frac{m}{tp} \rfloor \times \mu(t) \\ \end{aligned}
f ( x ) = p ∑ i = 1 ∑ n j = 1 ∑ m [ ( i , j ) = p ] = p ∑ t = 1 ∑ ⌊ p n ⌋ ⌊ t p n ⌋ × ⌊ t p m ⌋ × μ ( t ) 看起来好像和上面一样化简完了,但时间复杂度却是
O
(
c
n
t
n
)
O(cnt \sqrt n)
O ( c n t n
) ,其中
c
n
t
cnt
c n t 为
n
n
n 以内的质数数量。
在这种情况下,就又出现了一种常见的优化套路。
我们设
T
=
t
p
T = tp
T = t p ,结合
t
t
t 和
p
p
p 的范围,显然
T
∈
[
2
,
n
]
T\in[2,n]
T ∈ [ 2 , n ] 。
于是我们不再枚举
t
,
p
t,p
t , p ,而是直接枚举
T
T
T :
f
(
x
)
=
∑
T
=
2
n
∑
p
∣
T
⌊
n
T
⌋
×
⌊
m
T
⌋
×
μ
(
T
p
)
=
∑
T
=
2
n
⌊
n
T
⌋
×
⌊
m
T
⌋
×
∑
p
∣
T
μ
(
T
p
)
\begin{aligned} f(x)&=\sum_{T=2}^{n}\sum_{p|T}\lfloor \frac{n}{T} \rfloor \times \lfloor \frac{m}{T} \rfloor \times \mu(\frac{T}{p})\\ &=\sum_{T=2}^{n}\lfloor \frac{n}{T} \rfloor \times \lfloor \frac{m}{T} \rfloor \times \sum_{p|T}\mu(\frac{T}{p}) \end{aligned}
f ( x ) = T = 2 ∑ n p ∣ T ∑ ⌊ T n ⌋ × ⌊ T m ⌋ × μ ( p T ) = T = 2 ∑ n ⌊ T n ⌋ × ⌊ T m ⌋ × p ∣ T ∑ μ ( p T ) 然后我们发现,前半部分就是我们熟悉的除法分块,而上一个式子复杂度高的原因正在后半部分需要枚举
p
p
p 。考虑到这是多组询问,那么我们能不能把后半部分预处理出来呢?
很显然是可以的。
我们预处理时枚举
p
p
p ,对于
p
p
p 的倍数
T
T
T ,都加上
μ
(
T
p
)
\mu(\frac{T}{p})
μ ( p T ) 。复杂度是枚举质数再套枚举倍数,反正比原来小就对了。
然后对处理出来的答案做前缀和,再套除法分块即可。
预处理代码:
for ( int i = 1 ; i <= cnt; i++ ) {
for ( int j = 1 ; j* p[ i] <= n; j++ ) {
s[ j* p[ i] ] + = mu[ j] ;
}
}
for ( int i = 1 ; i <= n; i++ ) {
s[ i] + = s[ i- 1 ] ;
}
例题:P2257 YY的GCD
3.求约数个数和
设
d
(
x
)
d(x)
d ( x ) 表示
x
x
x 的约数和。给定
n
,
m
n,m
n , m ,求
∑
i
=
1
n
∑
j
=
1
m
d
(
i
j
)
\sum\limits_{i=1}^{n} \sum\limits_{j=1}^{m}d(ij)
i = 1 ∑ n j = 1 ∑ m d ( i j ) 。
首先,有一个不知名的但是很NB的公式(没错,我又不会证,想证明可以看下面例题的题解):
d
(
i
j
)
=
∑
x
∣
i
∑
y
∣
i
[
g
c
d
(
x
,
y
)
=
1
]
d(ij)=\sum_{x|i}\sum_{y|i}[gcd(x,y)=1]
d ( i j ) = x ∣ i ∑ y ∣ i ∑ [ g c d ( x , y ) = 1 ] 所以可以把原式进行一些转换:
a
n
s
=
∑
i
=
1
n
∑
j
=
1
m
∑
x
∣
i
∑
y
∣
i
[
g
c
d
(
x
,
y
)
=
1
]
\begin{aligned} ans &= \sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{x|i}\sum_{y|i}[gcd(x,y)=1] \\ \end{aligned}
a n s = i = 1 ∑ n j = 1 ∑ m x ∣ i ∑ y ∣ i ∑ [ g c d ( x , y ) = 1 ] 先枚举因数
x
,
y
x,y
x , y :
a
n
s
=
∑
x
=
1
n
∑
y
=
1
m
⌊
n
x
⌋
⌊
m
y
⌋
[
g
c
d
(
x
,
y
)
=
1
]
\begin{aligned} ans &= \sum_{x=1}^{n}\sum_{y=1}^{m}\lfloor \frac{n}{x} \rfloor \lfloor \frac{m}{y} \rfloor [gcd(x,y)=1] \end{aligned}
a n s = x = 1 ∑ n y = 1 ∑ m ⌊ x n ⌋ ⌊ y m ⌋ [ g c d ( x , y ) = 1 ]
设
f
(
k
)
=
∑
x
=
1
n
∑
y
=
1
m
⌊
n
x
⌋
⌊
m
y
⌋
[
g
c
d
(
x
,
y
)
=
k
]
g
(
k
)
=
∑
k
∣
d
f
(
d
)
=
∑
x
=
1
n
∑
y
=
1
m
⌊
n
x
⌋
⌊
m
y
⌋
[
k
∣
g
c
d
(
x
,
y
)
]
=
∑
x
=
1
⌊
n
k
⌋
∑
y
=
1
⌊
m
k
⌋
⌊
n
x
k
⌋
⌊
m
y
k
⌋
\begin{aligned} 设f(k) &= \sum_{x=1}^{n}\sum_{y=1}^{m}\lfloor \frac{n}{x} \rfloor \lfloor \frac{m}{y} \rfloor [gcd(x,y)=k]\\ g(k)&= \sum_{k|d}f(d) \\ &= \sum_{x=1}^{n}\sum_{y=1}^{m}\lfloor \frac{n}{x} \rfloor \lfloor \frac{m}{y} \rfloor [k|gcd(x,y)] \\ &= \sum_{x=1}^{\lfloor \frac{n}{k} \rfloor}\sum_{y=1}^{\lfloor \frac{m}{k} \rfloor}\lfloor \frac{n}{xk} \rfloor \lfloor \frac{m}{yk} \rfloor \end{aligned}
设 f ( k ) g ( k ) = x = 1 ∑ n y = 1 ∑ m ⌊ x n ⌋ ⌊ y m ⌋ [ g c d ( x , y ) = k ] = k ∣ d ∑ f ( d ) = x = 1 ∑ n y = 1 ∑ m ⌊ x n ⌋ ⌊ y m ⌋ [ k ∣ g c d ( x , y ) ] = x = 1 ∑ ⌊ k n ⌋ y = 1 ∑ ⌊ k m ⌋ ⌊ x k n ⌋ ⌊ y k m ⌋
接下来套公式反演一波:
f
(
k
)
=
∑
k
∣
d
g
(
d
)
×
μ
(
d
k
)
=
∑
k
∣
d
μ
(
d
k
)
×
∑
x
=
1
⌊
n
d
⌋
∑
y
=
1
⌊
m
d
⌋
⌊
n
x
d
⌋
⌊
m
y
d
⌋
\begin{aligned} f(k)&=\sum_{k|d}g(d)\times \mu(\frac{d}{k})\\ &= \sum_{k|d}\mu(\frac{d}{k})\times \sum_{x=1}^{\lfloor \frac{n}{d} \rfloor}\sum_{y=1}^{\lfloor \frac{m}{d} \rfloor}\lfloor \frac{n}{xd} \rfloor \lfloor \frac{m}{yd} \rfloor \end{aligned}
f ( k ) = k ∣ d ∑ g ( d ) × μ ( k d ) = k ∣ d ∑ μ ( k d ) × x = 1 ∑ ⌊ d n ⌋ y = 1 ∑ ⌊ d m ⌋ ⌊ x d n ⌋ ⌊ y d m ⌋ 那么我们发现我们的答案是
f
(
1
)
f(1)
f ( 1 ) ,于是化简一下(顺便把原式中的
x
,
y
x,y
x , y 换成
i
,
j
i,j
i , j ):
a
n
s
=
f
(
1
)
=
∑
d
=
1
n
μ
(
d
)
×
∑
i
=
1
⌊
n
d
⌋
∑
j
=
1
⌊
m
d
⌋
⌊
n
i
d
⌋
⌊
m
j
d
⌋
ans = f(1)=\sum_{d=1}^{n}\mu(d)\times \sum_{i=1}^{\lfloor \frac{n}{d} \rfloor}\sum_{j=1}^{\lfloor \frac{m}{d} \rfloor}\lfloor \frac{n}{id} \rfloor \lfloor \frac{m}{jd} \rfloor
a n s = f ( 1 ) = d = 1 ∑ n μ ( d ) × i = 1 ∑ ⌊ d n ⌋ j = 1 ∑ ⌊ d m ⌋ ⌊ i d n ⌋ ⌊ j d m ⌋ 然后发现后面两项之间没有关系:
a
n
s
=
∑
d
=
1
n
μ
(
d
)
×
(
∑
i
=
1
⌊
n
d
⌋
⌊
n
i
d
⌋
)
×
(
∑
j
=
1
⌊
m
d
⌋
⌊
m
j
d
⌋
)
ans =\sum_{d=1}^{n}\mu(d)\times (\sum_{i=1}^{\lfloor \frac{n}{d} \rfloor}\lfloor \frac{n}{id} \rfloor)\times (\sum_{j=1}^{\lfloor \frac{m}{d} \rfloor} \lfloor \frac{m}{jd} \rfloor)
a n s = d = 1 ∑ n μ ( d ) × ( i = 1 ∑ ⌊ d n ⌋ ⌊ i d n ⌋ ) × ( j = 1 ∑ ⌊ d m ⌋ ⌊ j d m ⌋ ) 我们可以先用一次除法分块预处理
s
(
x
)
=
∑
i
=
1
x
⌊
x
i
⌋
s(x)=\sum\limits_{i=1}^{x} \lfloor\frac{x}{i} \rfloor
s ( x ) = i = 1 ∑ x ⌊ i x ⌋ ,然后对
n
d
\frac{n}{d}
d n 再进行除法分块,同时对
μ
\mu
μ 求前缀和就可以
O
(
n
)
O(\sqrt n)
O ( n
) 求出答案。
预处理
s
s
s ,前缀和:
for ( int i = 1 ; i <= n; i++ ) mu[ i] + = mu[ i- 1 ] ;
for ( int i = 1 ; i <= n; i++ ) {
for ( int l = 1 , r; l <= i; l = r+ 1 ) {
r = i/ ( i/ l) ;
s[ i] + = ( ll) ( r- l+ 1 ) * ( i/ l) ;
}
}
除法分块回答询问:
for ( int l = 1 , r; l <= n; l = r+ 1 ) {
r = min ( n/ ( n/ l) , m/ ( m/ l) ) ;
ans + = ( mu[ r] - mu[ l- 1 ] ) * s[ n/ l] * s[ m/ l] ;
}
例题:P3327 约数个数和
到这里,我遇到过的一些套路就已经讲完了,本文也暂时完结。但以后可能会有更多的套路,有可能再更新。 (先挖坑再说,填不填全看心情)