莫比乌斯反演 莫比乌斯反演 莫比乌斯反演是数论中的重要内容。对于一些函数 f(n) ,如果很难直接求出它的值,而容易求出其倍数和或约数和 g(n) ,那么可以通过莫比乌斯反演简化运算,求得 f(n) 的值。
开始学习莫比乌斯反演前,需要先学习一些前置知识:数论分块 、狄利克雷卷积。
莫比乌斯函数 定义 \mu 为莫比乌斯函数,定义为
\mu(n)= \begin{cases} 1&n=1\\ 0&n\text{ 含有平方因子}\\ (-1)^k&k\text{ 为 }n\text{ 的本质不同质因子个数}\\ \end{cases} 含 有 平 方 因 子 为 的 本 质 不 同 质 因 子 个 数 详细解释一下:
令 n=\prod_{i=1}^kp_i^{c_i} ,其中 p_i 为质因子, c_i\ge 1 。上述定义表示:
n=1 时, \mu(n)=1 ; 对于 n\not= 1 时: 当存在 i\in [1,k] ,使得 c_i > 1 时, \mu(n)=0 ,也就是说只要某个质因子出现的次数超过一次, \mu(n) 就等于 0 ; 当任意 i\in[1,k] ,都有 c_i=1 时, \mu(n)=(-1)^k ,也就是说每个质因子都仅仅只出现过一次时,即 n=\prod_{i=1}^kp_i , \{p_i\}_{i=1}^k 中个元素唯一时, \mu(n) 等于 -1 的 k 次幂,此处 k 指的便是仅仅只出现过一次的质因子的总个数。 性质 莫比乌斯函数不仅是积性函数,还有如下性质:
\sum_{d\mid n}\mu(d)= \begin{cases} 1&n=1\\ 0&n\neq 1\\ \end{cases} 即 \sum_{d\mid n}\mu(d)=\varepsilon(n) , \mu * 1 =\varepsilon
证明 设 \displaystyle n=\prod_{i=1}^k{p_i}^{c_i},n'=\prod_{i=1}^k p_i
那么 \displaystyle\sum_{d\mid n}\mu(d)=\sum_{d\mid n'}\mu(d)=\sum_{i=0}^k C_k^i\cdot(-1)^i=(1+(-1))^k
根据二项式定理,易知该式子的值在 k=0 即 n=1 时值为 1 否则为 0 ,这也同时证明了 \displaystyle\sum_{d\mid n}\mu(d)=[n=1]=\varepsilon(n) 以及 \mu\ast 1=\varepsilon
注 这个性质意味着,莫比乌斯函数在狄利克雷生成函数中,等价于黎曼函数 \zeta 的倒数。所以在狄利克雷卷积中,莫比乌斯函数是常数函数 1 的逆元。
补充结论 反演结论: \displaystyle [\gcd(i,j)=1]=\sum_{d\mid\gcd(i,j)}\mu(d)
直接推导 :如果看懂了上一个结论,这个结论稍加思考便可以推出:如果 \gcd(i,j)=1 的话,那么代表着我们按上个结论中枚举的那个 n 是 1 ,也就是式子的值是 1 ,反之,有一个与 [\gcd(i,j)=1] 相同的值: 0
利用 \varepsilon 函数 :根据上一结论, [\gcd(i,j)=1]=\varepsilon(\gcd(i,j)) ,将 \varepsilon 展开即可。
线性筛 由于 \mu 函数为积性函数,因此可以线性筛莫比乌斯函数(线性筛基本可以求所有的积性函数,尽管方法不尽相同)。
线性筛实现 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// C++ Version
void getMu () {
mu [ 1 ] = 1 ;
for ( int i = 2 ; i <= n ; ++ i ) {
if ( ! flg [ i ]) p [ ++ tot ] = i , mu [ i ] = - 1 ;
for ( int j = 1 ; j <= tot && i * p [ j ] <= n ; ++ j ) {
flg [ i * p [ j ]] = 1 ;
if ( i % p [ j ] == 0 ) {
mu [ i * p [ j ]] = 0 ;
break ;
}
mu [ i * p [ j ]] = - mu [ i ];
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14# Python Version
def getMu ():
mu [ 1 ] = 1
for i in range ( 2 , n + 1 ):
if flg [ i ] != 0 :
p [ tot ] = i ; tot = tot + 1 ; mu [ i ] = - 1
j = 1
while j <= tot and i * p [ j ] <= n :
flg [ i * p [ j ]] = 1
if i % p [ j ] == 0 :
mu [ i * p [ j ]] = 0
break
mu [ i * p [ j ]] = mu [ i * p [ j ]] - mu [ i ]
j = j + 1
拓展 证明
\varphi \ast 1=\operatorname{id} 将 n 分解质因数: \displaystyle n=\prod_{i=1}^k {p_i}^{c_i}
首先,因为 \varphi 是积性函数,故只要证明当 n'=p^c 时 \displaystyle\varphi \ast 1=\sum_{d\mid n'}\varphi(\frac{n'}{d})=\operatorname{id} 成立即可。
因为 p 是质数,于是 d=p^0,p^1,p^2,\cdots,p^c
易知如下过程:
\begin{aligned} \varphi \ast 1&=\sum_{d\mid n}\varphi(\frac{n}{d})\\ &=\sum_{i=0}^c\varphi(p^i)\\ &=1+p^0\cdot(p-1)+p^1\cdot(p-1)+\cdots+p^{c-1}\cdot(p-1)\\ &=p^c\\ &=\operatorname{id}\\ \end{aligned} 该式子两侧同时卷 \mu 可得 \displaystyle\varphi(n)=\sum_{d\mid n}d\cdot\mu(\frac{n}{d})
莫比乌斯变换 设 f(n),g(n) 为两个数论函数。
形式一:如果有 f(n)=\sum_{d\mid n}g(d) ,那么有 g(n)=\sum_{d\mid n}\mu(d)f(\frac{n}{d}) 。
这种形式下,数论函数 f(n) 称为数论函数 g(n) 的莫比乌斯变换,数论函数 g(n) 称为数论函数 f(n) 的莫比乌斯逆变换(反演)。
容易看出,数论函数 g(n) 的莫比乌斯变换,就是将数论函数 g(n) 与常数函数 1 进行狄利克雷卷积。
注 根据狄利克雷卷积与狄利克雷生成函数的对应关系,数论函数 g(n) 的莫比乌斯变换对应的狄利克雷生成函数,就是数论函数 g(n) 的狄利克雷生成函数与黎曼函数 \zeta 的乘积。
形式二:如果有 f(n)=\sum_{n|d}g(d) ,那么有 g(n)=\sum_{n|d}\mu(\frac{d}{n})f(d) 。
证明 方法一:对原式做数论变换。
\sum_{d\mid n}\mu(d)f(\frac{n}{d})=\sum_{d\mid n}\mu(d)\sum_{k\mid \frac{n}{d}}g(k)=\sum_{k\mid n}g(k)\sum_{d\mid \frac{n}{k}}\mu(d)=g(n) 用 \displaystyle\sum_{d\mid n}g(d) 来替换 f(\dfrac{n}{d}) ,再变换求和顺序。最后一步变换的依据: \displaystyle\sum_{d\mid n}\mu(d)=[n=1] ,因此在 \dfrac{n}{k}=1 时第二个和式的值才为 1 。此时 n=k ,故原式等价于 \displaystyle\sum_{k\mid n}[n=k]\cdot g(k)=g(n)
方法二:运用卷积。
原问题为:已知 f=g\ast1 ,证明 g=f\ast\mu
易知如下转化: f\ast\mu=g*1*\mu\implies f\ast\mu=g (其中 1\ast\mu=\varepsilon )。
对于第二种形式:
类似上面的方法一,我们考虑逆推这个式子。
\begin{aligned} &\sum_{n|d}{\mu(\frac{d}{n})f(d)} \\ =& \sum_{k=1}^{+\infty}{\mu(k)f(kn)} = \sum_{k=1}^{+\infty}{\mu(k)\sum_{kn|d}{g(d)}} \\ =& \sum_{n|d}{g(d)\sum_{k|\frac{d}{n}}{\mu(k)}} = \sum_{n|d}{g(d)\epsilon(\frac{d}{n})} \\ =& g(n) \end{aligned} 我们把 d 表示为 kn 的形式,然后把 f 的原定义代入式子。
发现枚举 k 再枚举 kn 的倍数可以转换为直接枚举 n 的倍数再求出 k ,发现后面那一块其实就是 \epsilon , 整个式子只有在 d=n 的时候才能取到值。
问题形式 求值(多组数据)
\sum_{i=x}^{n}\sum_{j=y}^{m}[\gcd(i,j)=k]\qquad (1\leqslant T,x,y,n,m,k\leqslant 5\times 10^4) 根据容斥原理,原式可以分成 4 块来处理,每一块的式子都为
\sum_{i=1}^{n}\sum_{j=1}^{m}[\gcd(i,j)=k] 考虑化简该式子
\sum_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{k}\rfloor}[\gcd(i,j)=1] 因为 \gcd(i,j)=1 时对答案才用贡献,于是我们可以将其替换为 \varepsilon(\gcd(i,j)) ( \varepsilon(n) 当且仅当 n=1 时值为 1 否则为 0 ),故原式化为
\sum_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{k}\rfloor}\varepsilon(\gcd(i,j)) 将 \varepsilon 函数展开得到
\displaystyle\sum_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{k}\rfloor}\sum_{d\mid \gcd(i,j)}\mu(d) 变换求和顺序,先枚举 d\mid \gcd(i,j) 可得
\displaystyle\sum_{d=1}\mu(d)\sum_{i=1}^{\lfloor\frac{n}{k}\rfloor}[d\mid i]\sum_{j=1}^{\lfloor\frac{m}{k}\rfloor}[d\mid j] 易知 1\sim\lfloor\dfrac{n}{k}\rfloor 中 d 的倍数有 \lfloor\dfrac{n}{kd}\rfloor 个,故原式化为
\displaystyle\sum_{d=1}^{\min(\lfloor \frac{n}{k}\rfloor,\lfloor \frac{m}{k}\rfloor)}\mu(d)\lfloor\frac{n}{kd}\rfloor\lfloor\frac{m}{kd}\rfloor 很显然,式子可以数论分块求解。
时间复杂度 \Theta(N+T\sqrt{n})
代码实现 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49#include <algorithm>
#include <cstdio>
using namespace std ;
const int N = 50000 ;
int mu [ N + 5 ], p [ N + 5 ];
bool flg [ N + 5 ];
void init () {
int tot = 0 ;
mu [ 1 ] = 1 ;
for ( int i = 2 ; i <= N ; ++ i ) {
if ( ! flg [ i ]) {
p [ ++ tot ] = i ;
mu [ i ] = - 1 ;
}
for ( int j = 1 ; j <= tot && i * p [ j ] <= N ; ++ j ) {
flg [ i * p [ j ]] = 1 ;
if ( i % p [ j ] == 0 ) {
mu [ i * p [ j ]] = 0 ;
break ;
}
mu [ i * p [ j ]] = - mu [ i ];
}
}
for ( int i = 1 ; i <= N ; ++ i ) mu [ i ] += mu [ i - 1 ];
}
int solve ( int n , int m ) {
int res = 0 ;
for ( int i = 1 , j ; i <= min ( n , m ); i = j + 1 ) {
j = min ( n / ( n / i ), m / ( m / i ));
res += ( mu [ j ] - mu [ i - 1 ]) * ( n / i ) * ( m / i ); //代推出来的式子
}
return res ;
}
int main () {
int T , a , b , c , d , k ;
init (); //预处理mu数组
scanf ( "%d" , & T );
for ( int i = 1 ; i <= T ; i ++ ) {
scanf ( "%d%d%d%d%d" , & a , & b , & c , & d , & k );
//根据容斥原理,1<=x<=b&&1<=y<=d范围中的答案数减去1<=x<=b&&1<=y<=c-1范围中的答案数和
// 1<=x<=a-1&&1<=y<=d范围中的答案数再加上1<=x<=a-1&&1<=y<=c-1范围中的答案数
// 即可得到a<=x<=b&&c<=y<=d范围中的答案数
//这一步如果不懂可以画坐标图进行理解
printf ( "%d \n " , solve ( b / k , d / k ) - solve ( b / k , ( c - 1 ) / k ) -
solve (( a - 1 ) / k , d / k ) +
solve (( a - 1 ) / k , ( c - 1 ) / k ));
}
return 0 ;
}
求值(多组数据)
\sum_{i=1}^n \operatorname{lcm}(i,n)\quad \text{s.t.}\ 1\leqslant T\leqslant 3\times 10^5,1\leqslant n\leqslant 10^6 易得原式即
\sum_{i=1}^n \frac{i\cdot n}{\gcd(i,n)} 将原式复制一份并且颠倒顺序,然后将 n 一项单独提出,可得
\frac{1}{2}\cdot \left(\sum_{i=1}^{n-1}\frac{i\cdot n}{\gcd(i,n)}+\sum_{i=n-1}^{1}\frac{i\cdot n}{\gcd(i,n)}\right)+n 根据 \gcd(i,n)=\gcd(n-i,n) ,可将原式化为
\frac{1}{2}\cdot \left(\sum_{i=1}^{n-1}\frac{i\cdot n}{\gcd(i,n)}+\sum_{i=n-1}^{1}\frac{i\cdot n}{\gcd(n-i,n)}\right)+n 两个求和式中分母相同的项可以合并。
\frac{1}{2}\cdot \sum_{i=1}^{n-1}\frac{n^2}{\gcd(i,n)}+n 即
\frac{1}{2}\cdot \sum_{i=1}^{n}\frac{n^2}{\gcd(i,n)}+\frac{n}{2} 可以将相同的 \gcd(i,n) 合并在一起计算,故只需要统计 \gcd(i,n)=d 的个数。当 \gcd(i,n)=d 时, \displaystyle\gcd(\frac{i}{d},\frac{n}{d})=1 ,所以 \gcd(i,n)=d 的个数有 \displaystyle\varphi(\frac{n}{d}) 个。
故答案为
\frac{1}{2}\cdot\sum_{d\mid n}\frac{n^2\cdot\varphi(\frac{n}{d})}{d}+\frac{n}{2} 变换求和顺序,设 \displaystyle d'=\frac{n}{d} ,合并公因式,式子化为
\frac{1}{2}n\cdot\left(\sum_{d'\mid n}d'\cdot\varphi(d')+1\right) 设 \displaystyle \operatorname{g}(n)=\sum_{d\mid n} d\cdot\varphi(d) ,已知 \operatorname{g} 为积性函数,于是可以 \Theta(n) 筛出。每次询问 \Theta(1) 计算即可。
下面给出这个函数筛法的推导过程:
首先考虑 \operatorname g(p_j^k) 的值,显然它的约数只有 p_j^0,p_j^1,\cdots,p_j^k ,因此
\operatorname g(p_j^k)=\sum_{w=0}^{k}p_j^w\cdot\varphi(p_j^w) 又有 \varphi(p_j^w)=p_j^{w-1}\cdot(p_j-1) ,则原式可化为
\sum_{w=0}^{k}p_j^{2w-1}\cdot(p_j-1) 于是有
\operatorname g(p_j^{k+1})=\operatorname g(p_j^k)+p_j^{2k+1}\cdot(p_j-1) 那么,对于线性筛中的 \operatorname g(i\cdot p_j)(p_j|i) ,令 i=a\cdot p_j^w(\operatorname{gcd}(a,p_j)=1) ,可得
\operatorname g(i\cdot p_j)=\operatorname g(a)\cdot\operatorname g(p_j^{w+1}) \operatorname g(i)=\operatorname g(a)\cdot\operatorname g(p_j^w) 即
\operatorname g(i\cdot p_j)-\operatorname g(i)=\operatorname g(a)\cdot p_j^{2w+1}\cdot(p_j-1) 同理有
\operatorname g(i)-\operatorname g(\frac{i}{p_j})=\operatorname g(a)\cdot p_j^{2w-1}\cdot(p_j-1) 因此
\operatorname g(i\cdot p_j)=\operatorname g(i)+\left (\operatorname g(i)-\operatorname g(\frac{i}{p_j})\right )\cdot p_j^2 时间复杂度 : \Theta(n+T)
代码实现 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34#include <cstdio>
const int N = 1000000 ;
int tot , p [ N + 5 ];
long long g [ N + 5 ];
bool flg [ N + 5 ]; //标记数组
void solve () {
g [ 1 ] = 1 ;
for ( int i = 2 ; i <= N ; ++ i ) {
if ( ! flg [ i ]) {
p [ ++ tot ] = i ;
g [ i ] = ( long long ) 1 * i * ( i - 1 ) + 1 ;
}
for ( int j = 1 ; j <= tot && i * p [ j ] <= N ; ++ j ) {
flg [ i * p [ j ]] = 1 ;
if ( i % p [ j ] == 0 ) {
g [ i * p [ j ]] =
g [ i ] + ( g [ i ] - g [ i / p [ j ]]) * p [ j ] * p [ j ]; //代入推出来的式子
break ;
}
g [ i * p [ j ]] = g [ i ] * g [ p [ j ]];
}
}
}
int main () {
int T , n ;
solve (); //预处理g数组
scanf ( "%d" , & T );
for ( int i = 1 ; i <= T ; ++ i ) {
scanf ( "%d" , & n );
printf ( "%lld \n " , ( g [ n ] + 1 ) * n / 2 );
}
return 0 ;
}
求值(对 20101009 取模)
\sum_{i=1}^n\sum_{j=1}^m\operatorname{lcm}(i,j)\qquad (n,m\leqslant 10^7) 易知原式等价于
\sum_{i=1}^n\sum_{j=1}^m\frac{i\cdot j}{\gcd(i,j)} 枚举最大公因数 d ,显然两个数除以 d 得到的数互质
\sum_{i=1}^n\sum_{j=1}^m\sum_{d\mid i,d\mid j,\gcd(\frac{i}{d},\frac{j}{d})=1}\frac{i\cdot j}{d} 非常经典的 \gcd 式子的化法
\sum_{d=1}^n d\cdot\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}[\gcd(i,j)=1]\ i\cdot j 后半段式子中,出现了互质数对之积的和,为了让式子更简洁就把它拿出来单独计算。于是我们记
\operatorname{sum}(n,m)=\sum_{i=1}^n\sum_{j=1}^m [\gcd(i,j)=1]\ i\cdot j 接下来对 \operatorname{sum}(n,m) 进行化简。首先枚举约数,并将 [\gcd(i,j)=1] 表示为 \varepsilon(\gcd(i,j))
\sum_{d=1}^n\sum_{d\mid i}^n\sum_{d\mid j}^m\mu(d)\cdot i\cdot j 设 i=i'\cdot d , j=j'\cdot d ,显然式子可以变为
\sum_{d=1}^n\mu(d)\cdot d^2\cdot\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}i\cdot j 观察上式,前半段可以预处理前缀和;后半段又是一个范围内数对之和,记
g(n,m)=\sum_{i=1}^n\sum_{j=1}^m i\cdot j=\frac{n\cdot(n+1)}{2}\times\frac{m\cdot(m+1)}{2} 可以 \Theta(1) 求解
至此
\operatorname{sum}(n,m)=\sum_{d=1}^n\mu(d)\cdot d^2\cdot g(\lfloor\frac{n}{d}\rfloor,\lfloor\frac{m}{d}\rfloor) 我们可以 \lfloor\frac{n}{\lfloor\frac{n}{d}\rfloor}\rfloor 数论分块求解 \operatorname{sum}(n,m) 函数。
在求出 \operatorname{sum}(n,m) 后,回到定义 \operatorname{sum} 的地方,可得原式为
\sum_{d=1}^n d\cdot\operatorname{sum}(\lfloor\frac{n}{d}\rfloor,\lfloor\frac{m}{d}\rfloor) 可见这又是一个可以数论分块求解的式子!
本题除了推式子比较复杂、代码细节较多之外,是一道很好的莫比乌斯反演练习题!(上述过程中,默认 n\leqslant m )
时间复杂度: \Theta(n+m) (瓶颈为线性筛)
代码实现 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64#include <algorithm>
#include <cstdio>
using namespace std ;
const int N = 1e7 ;
const int mod = 20101009 ;
int n , m , mu [ N + 5 ], p [ N / 10 + 5 ], sum [ N + 5 ];
bool flg [ N + 5 ];
int Sum ( int x , int y ) {
return (( long long ) 1 * x * ( x + 1 ) / 2 % mod ) *
(( long long ) 1 * y * ( y + 1 ) / 2 % mod ) % mod ;
}
int func ( int x , int y ) {
int res = 0 ;
int j ;
for ( int i = 1 ; i <= min ( x , y ); i = j + 1 ) {
j = min ( x / ( x / i ), y / ( y / i ));
res = ( res + ( long long ) 1 * ( sum [ j ] - sum [ i - 1 ] + mod ) *
Sum ( x / i , y / i ) % mod ) %
mod ; //+mod防负数
}
return res ;
}
int solve ( int x , int y ) {
int res = 0 ;
int j ;
for ( int i = 1 ; i <= min ( x , y ); i = j + 1 ) { //整除分块处理
j = min ( x / ( x / i ), y / ( y / i ));
res = ( res + ( long long ) 1 * ( j - i + 1 ) * ( i + j ) / 2 % mod *
func ( x / i , y / i ) % mod ) %
mod ; //!每步取模防爆
}
return res ;
}
void init () { //线性筛
mu [ 1 ] = 1 ;
int tot = 0 , k = min ( n , m );
for ( int i = 2 ; i <= k ; ++ i ) {
if ( ! flg [ i ]) {
p [ ++ tot ] = i ;
mu [ i ] = - 1 ;
}
for ( int j = 1 ; j <= tot && i * p [ j ] <= k ; ++ j ) {
flg [ i * p [ j ]] = 1 ;
if ( i % p [ j ] == 0 ) {
mu [ i * p [ j ]] = 0 ;
break ;
}
mu [ i * p [ j ]] = - mu [ i ];
}
}
for ( int i = 1 ; i <= k ; ++ i )
sum [ i ] = ( sum [ i - 1 ] + ( long long ) 1 * i * i % mod * ( mu [ i ] + mod )) % mod ;
}
int main () {
scanf ( "%d%d" , & n , & m );
init ();
printf ( "%d \n " , solve ( n , m ));
}
多组数据,求
\sum_{i=1}^n\sum_{j=1}^md(i\cdot j)\\ \left(d(n)=\sum_{i \mid n}1\right) n,m,T\leq5\times10^4 其中 d(n) 表示 n 的约数个数
要推这道题首先要了解 d 函数的一个特殊性质
d(i\cdot j)=\sum_{x \mid i}\sum_{y \mid j}[\gcd(x,y)=1] 再化一下这个式子
\begin{aligned} d(i\cdot j)=&\sum_{x \mid i}\sum_{y \mid j}[\gcd(x,y)=1]\\ =&\sum_{x \mid i}\sum_{y \mid j}\sum_{p \mid \gcd(x,y)}\mu(p)\\ =&\sum_{p=1}^{min(i,j)}\sum_{x \mid i}\sum_{y \mid j}[p \mid \gcd(x,y)]\cdot\mu(p)\\ =&\sum_{p \mid i,p \mid j}\mu(p)\sum_{x \mid i}\sum_{y \mid j}[p \mid \gcd(x,y)]\\ =&\sum_{p \mid i,p \mid j}\mu(p)\sum_{x \mid \frac{i}{p}}\sum_{y \mid \frac{j}{p}}1\\ =&\sum_{p \mid i,p \mid j}\mu(p)d\left(\frac{i}{p}\right)d\left(\frac{j}{p}\right)\\ \end{aligned} 将上述式子代回原式
\begin{aligned} &\sum_{i=1}^n\sum_{j=1}^md(i\cdot j)\\ =&\sum_{i=1}^n\sum_{j=1}^m\sum_{p \mid i,p \mid j}\mu(p)d\left(\frac{i}{p}\right)d\left(\frac{j}{p}\right)\\ =&\sum_{p=1}^{min(n,m)} \sum_{i=1}^n\sum_{j=1}^m [p \mid i,p \mid j]\cdot\mu(p)d\left(\frac{i}{p}\right)d\left(\frac{j}{p}\right)\\ =&\sum_{p=1}^{min(n,m)} \sum_{i=1}^{\left\lfloor\frac{n}{p}\right\rfloor}\sum_{j=1}^{\left\lfloor\frac{m}{p}\right\rfloor} \mu(p)d(i)d(j)\\ =&\sum_{p=1}^{min(n,m)}\mu(p) \sum_{i=1}^{\left\lfloor\frac{n}{p}\right\rfloor}d(i) \sum_{j=1}^{\left\lfloor\frac{m}{p}\right\rfloor}d(j)\\ =&\sum_{p=1}^{min(n,m)}\mu(p) S\left(\left\lfloor\frac{n}{p}\right\rfloor\right) S\left(\left\lfloor\frac{m}{p}\right\rfloor\right) \left(S(n)=\sum_{i=1}^{n}d(i)\right)\\ \end{aligned} 那么 O(n) 预处理 \mu,d 的前缀和, O(\sqrt{n}) 分块处理询问,总复杂度 O(n+T\sqrt{n}) .
代码实现 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46#include <algorithm>
#include <cstdio>
using namespace std ;
const long long N = 5e4 + 5 ;
long long n , m , T , pr [ N ], mu [ N ], d [ N ], t [ N ],
cnt ; // t 表示 i 的最小质因子出现的次数
bool bp [ N ];
void prime_work ( long long k ) {
bp [ 0 ] = bp [ 1 ] = 1 , mu [ 1 ] = 1 , d [ 1 ] = 1 ;
for ( long long i = 2 ; i <= k ; i ++ ) { //线性筛
if ( ! bp [ i ]) pr [ ++ cnt ] = i , mu [ i ] = - 1 , d [ i ] = 2 , t [ i ] = 1 ;
for ( long long j = 1 ; j <= cnt && i * pr [ j ] <= k ; j ++ ) {
bp [ i * pr [ j ]] = 1 ;
if ( i % pr [ j ] == 0 ) {
mu [ i * pr [ j ]] = 0 ;
d [ i * pr [ j ]] = d [ i ] / ( t [ i ] + 1 ) * ( t [ i ] + 2 );
t [ i * pr [ j ]] = t [ i ] + 1 ;
break ;
} else {
mu [ i * pr [ j ]] = - mu [ i ];
d [ i * pr [ j ]] = d [ i ] << 1 ;
t [ i * pr [ j ]] = 1 ;
}
}
}
for ( long long i = 2 ; i <= k ; i ++ )
mu [ i ] += mu [ i - 1 ], d [ i ] += d [ i - 1 ]; //求前缀和
}
long long solve () {
long long res = 0 , mxi = min ( n , m );
for ( long long i = 1 , j ; i <= mxi ; i = j + 1 ) { //整除分块
j = min ( n / ( n / i ), m / ( m / i ));
res += d [ n / i ] * d [ m / i ] * ( mu [ j ] - mu [ i - 1 ]);
}
return res ;
}
int main () {
scanf ( "%lld" , & T );
prime_work ( 50000 ); //预处理
while ( T -- ) {
scanf ( "%lld%lld" , & n , & m );
printf ( "%lld \n " , solve ());
}
return 0 ;
}
另一种推导方式
转化一下,可以将式子写成
\begin{aligned} &\sum_{d=1}^{n}d^3\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{d}\rfloor}ij\cdot[\gcd(i,j)=1]\\ =&\sum_{d=1}^{n}d^3\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{d}\rfloor}ij\sum_{t\mid \gcd(i,j)}\mu(t)\\ =&\sum_{d=1}^{n}d^3\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{d}\rfloor}ij\sum_{t=1}^{\lfloor\frac{n}{d}\rfloor}\mu(t)[t\mid \gcd(i,j)]\\ =&\sum_{d=1}^{n}d^3\sum_{t=1}^{\lfloor\frac{n}{d}\rfloor}t^2 \mu(t)\sum_{i=1}^{\lfloor\frac{n}{td}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{td}\rfloor}ij[1\mid \gcd(i,j)]\\ =&\sum_{d=1}^{n}d^3\sum_{t=1}^{\lfloor\frac{n}{d}\rfloor}t^2 \mu(t)\sum_{i=1}^{\lfloor\frac{n}{td}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{td}\rfloor}ij \end{aligned} 容易知道
\sum_{i=1}^{n}i=\frac{n(n+1)}{2} 设 F(n)=\sum_{i=1}^{n}i ,继续接着前面的往下推
\begin{aligned} &\sum_{d=1}^{n}d^3\sum_{t=1}^{\lfloor\frac{n}{d}\rfloor}t^2 \mu(t)\sum_{i=1}^{\lfloor\frac{n}{td}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{td}\rfloor}ij\\ =&\sum_{d=1}^{n}d^3\sum_{t=1}^{\lfloor\frac{n}{d}\rfloor}t^2 \mu(t)\cdot F^2\left(\left\lfloor\frac{n}{td}\right\rfloor\right)\\ =&\sum_{T=1}^{n}F^2\left(\left\lfloor\frac{n}{T}\right\rfloor\right) \sum_{d\mid T}d^3\left(\frac{T}{d}\right)^2\mu\left(\frac{T}{d}\right)\\ =&\sum_{T=1}^{n}F^2\left(\left\lfloor\frac{n}{T}\right\rfloor\right) T^2\sum_{d\mid T}d\cdot\mu\left(\dfrac{T}{d}\right) \end{aligned} 利用 \operatorname{id}\ast \mu = \varphi 反演,上式等于
\sum_{T=1}^{n}F^2\left(\left\lfloor\frac{n}{T}\right\rfloor\right) T^2\varphi(T)
得到了一个与第一种推导本质相同的式子。
莫比乌斯反演扩展 结尾补充一个莫比乌斯反演的非卷积形式。
对于数论函数 f,g 和完全积性函数 t 且 t(1)=1 :
f(n)=\sum_{i=1}^nt(i)g\left(\left\lfloor\frac{n}{i}\right\rfloor\right)\\ \iff g(n)=\sum_{i=1}^n\mu(i)t(i)f\left(\left\lfloor\frac{n}{i}\right\rfloor\right) 我们证明一下
\begin{aligned} g(n)&=\sum_{i=1}^n\mu(i)t(i)f\left(\left\lfloor\frac{n}{i}\right\rfloor\right)\\ &=\sum_{i=1}^n\mu(i)t(i) \sum_{j=1}^{\left\lfloor\frac{n}{i}\right\rfloor}t(j) g\left(\left\lfloor\frac{\left\lfloor\frac{n}{i}\right\rfloor}{j}\right\rfloor\right)\\ &=\sum_{i=1}^n\mu(i)t(i) \sum_{j=1}^{\left\lfloor\frac{n}{i}\right\rfloor}t(j) g\left(\left\lfloor\frac{n}{ij}\right\rfloor\right)\\ &=\sum_{T=1}^n \sum_{i=1}^n\mu(i)t(i) \sum_{j=1}^{\left\lfloor\frac{n}{i}\right\rfloor}[ij=T] t(j)g\left(\left\lfloor\frac{n}{T}\right\rfloor\right) &\text{【先枚举 ij 乘积】}\\ &=\sum_{T=1}^n \sum_{i \mid T}\mu(i)t(i) t\left(\frac{T}{i}\right)g\left(\left\lfloor\frac{n}{T}\right\rfloor\right) &\text{【}\sum_{j=1}^{\left\lfloor\frac{n}{i}\right\rfloor}[ij=T] \text{对答案的贡献为 1,于是省略】}\\ &=\sum_{T=1}^ng\left(\left\lfloor\frac{n}{T}\right\rfloor\right) \sum_{i \mid T}\mu(i)t(i)t\left(\frac{T}{i}\right)\\ &=\sum_{T=1}^ng\left(\left\lfloor\frac{n}{T}\right\rfloor\right) \sum_{i \mid T}\mu(i)t(T) &\text{【t 是完全积性函数】}\\ &=\sum_{T=1}^ng\left(\left\lfloor\frac{n}{T}\right\rfloor\right)t(T) \sum_{i \mid T}\mu(i)\\ &=\sum_{T=1}^ng\left(\left\lfloor\frac{n}{T}\right\rfloor\right)t(T) \varepsilon(T) &\text{【}\mu\ast 1= \varepsilon\text{】}\\ &=g(n)t(1) &\text{【当且仅当 T=1,}\varepsilon(T)=1\text{时】}\\ &=g(n) & \square \end{aligned} 【 先 枚 举 乘 积 】 【 对 答 案 的 贡 献 为 , 于 是 省 略 】 【 是 完 全 积 性 函 数 】 【 】 【 当 且 仅 当 时 】 参考文献 algocode 算法博客
build 本页面最近更新: ,更新历史 edit 发现错误?想一起完善? 在 GitHub 上编辑此页! people 本页面贡献者:hydingsy, hyp1231, ranwen copyright 本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用