浅谈莫比乌斯反演
简介( ch e ˇ d a ˋ n \text{chě dàn} cheˇ daˋn):
莫比乌斯反演是数论中的重要内容。对于一些函数 ,如果很难直接求出它的值,而容易求出其倍数和或约数和 ,那么可以通过莫比乌斯反演简化运算,进行求值。
前置芝士:
引理 1 1 1: ∀ a , b , c ∈ Z , ⌊ a b c ⌋ = ⌊ ⌊ a b ⌋ c ⌋ \forall a,b,c \in Z, \lfloor \frac{a}{bc}\rfloor = \lfloor \frac{\lfloor \frac{a}{b} \rfloor}{c} \rfloor ∀a,b,c∈Z,⌊bca⌋=⌊c⌊ba⌋⌋
引理 2 2 2: ∀ n ∈ N + , ∣ { ⌊ n d ⌋ ∣ d ∈ N + , d ≤ n } ∣ ≤ ⌊ 2 n ⌋ \forall n \in N_+, \vert \{ \lfloor \frac{n}{d} \rfloor \vert d\in N_+,d\le n \}\vert \le \lfloor2\sqrt{n}\rfloor ∀n∈N+,∣{⌊dn⌋∣d∈N+,d≤n}∣≤⌊2n⌋
Tips:
∣
{
}
∣
\vert\{\}\vert
∣{}∣表示集合的长度,即集合中元素的个数。
1.整除分块:
用来求
∑
⌊
n
i
⌋
\sum\lfloor\frac{n}{i}\rfloor
∑⌊in⌋,直接模拟时间复杂度为
O
(
n
)
O(n)
O(n),但是用整除分块可以优化到
O
(
n
)
O(\sqrt n)
O(n)。
对于
∀
i
≤
n
\forall i \le n
∀i≤n ,我们需要找到一个
i
≤
j
m
a
x
≤
n
i \le j_{max} \le n
i≤jmax≤n ,使得
⌊
n
i
⌋
=
⌊
n
j
m
a
x
⌋
\lfloor\frac{n}{i}\rfloor=\lfloor\frac{n}{j_{max}}\rfloor
⌊in⌋=⌊jmaxn⌋。
很容易发现:
r
=
⌊
n
⌊
n
i
⌋
⌋
r=\lfloor\frac{n}{\lfloor\frac{n}{i}\rfloor}\rfloor
r=⌊⌊in⌋n⌋。(证明过程详见Oi-wiki)
例题:
P2261 [CQOI2007]余数求和
题目描述:
给出正整数
n
n
n 和
k
k
k,请计算
G
(
n
,
k
)
=
∑
i
=
1
n
k
m
o
d
i
G(n, k) = \sum\limits_{i = 1}^n k \bmod i
G(n,k)=i=1∑nkmodi
其中
k
m
o
d
i
k\bmod i
kmodi 表示
k
k
k 除以
i
i
i 的余数。
S
o
l
u
t
i
o
n
:
\tt Solution:
Solution:
一道非常基础的模板题,我们先来化简。
A
n
s
=
∑
i
=
1
n
k
m
o
d
i
Ans=\sum\limits_{i=1}^nk\bmod i
Ans=i=1∑nkmodi
=
∑
i
=
1
n
k
−
⌊
k
i
⌋
×
i
=\sum\limits_{i=1}^nk - \lfloor\frac{k}{i}\rfloor\times i
=i=1∑nk−⌊ik⌋×i
=
n
×
k
−
∑
i
=
1
n
⌊
k
i
⌋
×
i
=n\times k - \sum\limits_{i=1}^n\lfloor\frac{k}{i}\rfloor\times i
=n×k−i=1∑n⌊ik⌋×i
然后就直接用整除分块做就行了
C
o
d
e
:
\tt Code:
Code:
#include <bits/stdc++.h>
using namespace std;
long long n, k, ans;
int main() {
scanf("%lld%lld", &n, &k);
ans = n * k;
for (int l = 1, r; l <= n; l = r + 1) {
if (k / l) r = min(k / (k / l), n);
else r = n;
ans -= (k / l) * (r - l + 1) * (l + r) / 2;
}
printf("%lld", ans);
return 0;
}
2.狄利克雷卷积与数论函数
定义:
- 数论函数: 值域为整数的函数。
- 狄利克雷卷积: ( f ∗ g ) ( n ) = ∑ d ∣ n f ( d ) g ( n d ) (f*g)(n)=\sum\limits_{d\vert n}f(d)g(\frac{n}{d}) (f∗g)(n)=d∣n∑f(d)g(dn)或者 ( f ∗ g ) ( n ) = ∑ x × y = n f ( x ) g ( y ) (f*g)(n)=\sum\limits_{x\times y =n}f(x)g(y) (f∗g)(n)=x×y=n∑f(x)g(y)
狄利克雷卷积的性质:
- 交换律: f ∗ g = g ∗ f f*g=g*f f∗g=g∗f
- 结合律: ( f ∗ g ) ∗ h = f ∗ ( g ∗ h ) (f*g)*h=f*(g*h) (f∗g)∗h=f∗(g∗h)
- 分配律: f ∗ ( g + h ) = f ∗ g + f ∗ h f*(g+h)=f*g+f*h f∗(g+h)=f∗g+f∗h
-
f
∗
ε
=
f
f*\varepsilon=f
f∗ε=f
积性函数:
定义:
- 对于
g
c
d
(
a
,
b
)
=
1
gcd(a,b)=1
gcd(a,b)=1,有
{
f
(
1
)
=
1
f
(
a
b
)
=
f
(
a
)
×
f
(
b
)
\begin{cases}f(1)=1\\f(ab)=f(a)\times f(b)\end{cases}
{f(1)=1f(ab)=f(a)×f(b),则
f
(
x
)
f(x)
f(x)被称为积性函数。
- 对于
∀
a
,
b
∈
C
\forall a,b \in C
∀a,b∈C,有
{
f
(
1
)
=
1
f
(
a
b
)
=
f
(
a
)
×
f
(
b
)
\begin{cases}f(1)=1\\f(ab)=f(a)\times f(b)\end{cases}
{f(1)=1f(ab)=f(a)×f(b),则
f
(
x
)
f(x)
f(x)被称为完全积性函数。
结论:
- 两个积性函数的狄利克雷卷积还是积性函数。
- 积性函数的逆还是积性函数。
常见的积性函数:
- 恒等函数:
I
(
n
)
≡
1
\Iota(n) \equiv 1
I(n)≡1(无论
n
n
n是啥,恒等于1,
废柴一个) - 元函数: ε ( n ) = [ n = 1 ] \varepsilon(n)=[n=1] ε(n)=[n=1]
- 单位函数: i d ( n ) = n id(n)=n id(n)=n
- 莫比乌斯函数:
μ
(
x
)
=
{
0
∃
d
>
1
且
d
2
∣
x
(
−
1
)
k
x
=
∏
i
=
1
k
p
i
(
p
i
∈
p
r
i
m
e
)
\mu(x)=\begin{cases}0&\exists d>1且d^2|x\\(-1)^k&x=\prod\limits_{i=1}^kp_i(p_i\in {\tt prime})\end{cases}
μ(x)=⎩⎨⎧0(−1)k∃d>1且d2∣xx=i=1∏kpi(pi∈prime)
莫比乌斯函数的性质: μ ∗ I = ∑ d ∣ n μ ( d ) = [ n = 1 ] = ε \mu*\Iota=\sum\limits_{d|n}\mu(d)=[n=1]=\varepsilon μ∗I=d∣n∑μ(d)=[n=1]=ε
莫比乌斯函数的模板如下:void Mobius() { Mu[1] = 1; for (int i = 2; i <= Maxn; i++) { if (!vis[i]) Mu[i] = -1, p[++cnt] = i; for (int j = 1; j <= cnt && (int)i * p[j] <= Maxn; j++) { vis[i * p[j]] = true; if (i % p[j] == 0) break; Mu[i * p[j]] = -Mu[i]; } Mu[i] += Mu[i - 1]; } }
然后进入正题:
3.莫比乌斯反演
设两个数论函数
F
(
x
)
,
f
(
x
)
F(x),f(x)
F(x),f(x),则有:
{
F
(
n
)
=
∑
d
∣
n
f
(
d
)
①
f
(
n
)
=
∑
d
∣
n
μ
(
d
)
F
(
n
d
)
②
f
(
n
)
=
∑
n
∣
d
μ
(
d
n
)
F
(
d
)
③
\begin{cases}F(n)=\sum\limits_{d|n}f(d)&①\\f(n)=\sum\limits_{d|n}\mu(d)F(\frac{n}{d})&②\\f(n)=\sum\limits_{n|d}\mu(\frac{d}{n})F(d)&③\end{cases}
⎩⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎧F(n)=d∣n∑f(d)f(n)=d∣n∑μ(d)F(dn)f(n)=n∣d∑μ(nd)F(d)①②③
证:
由①可得:
F
∗
μ
=
f
∗
I
∗
μ
F*\mu=f*\Iota*\mu
F∗μ=f∗I∗μ
由莫比乌斯函数的性质可得:
F
∗
μ
=
f
∗
ε
=
f
F*\mu=f*\varepsilon=f
F∗μ=f∗ε=f
所以,
f
=
μ
∗
F
=
∑
d
∣
n
μ
(
d
)
F
(
n
d
)
f=\mu*F=\sum\limits_{d|n}\mu(d)F(\frac{n}{d})
f=μ∗F=d∣n∑μ(d)F(dn)
例题:
P3455 [POI2007]ZAP-Queries
题目描述:
密码学家正在尝试破解一种叫 B S A BSA BSA 的密码。
他发现,在破解一条消息的同时,他还需要回答这样一种问题:
给出 a , b , d a,b,d a,b,d求满足 1 ≤ x ≤ a , 1 ≤ y ≤ b 1 \leq x \leq a,1 \leq y \leq b 1≤x≤a,1≤y≤b,且 gcd ( x , y ) = d \gcd(x,y)=d gcd(x,y)=d 的二元组 ( x , y ) (x,y) (x,y) 的数量。
因为要解决的问题实在太多了,他便过来寻求你的帮助。
输入格式:
输入第一行一个整数 n n n,代表要回答的问题个数。
接下来 n n n 行,每行三个整数 a , b , d a,b,d a,b,d。
输出格式:
对于每组询问,输出一个整数代表答案。
S
o
l
u
t
i
o
n
:
\tt Solution:
Solution:
首先我们先把题意转换成人能看懂 的样子。
题目让我们求的东西:
∑ x = 1 a ∑ y = 1 b [ gcd ( x , y ) = d ] \sum\limits_{x=1}^a\sum\limits_{y=1}^b{[\gcd(x,y)=d]} x=1∑ay=1∑b[gcd(x,y)=d]
我们先把 d d d提出来:
∑ x = 1 a d ∑ y = 1 b d [ gcd ( x , y ) = 1 ] \sum\limits_{x=1}^{\frac{a}{d}}\sum\limits_{y=1}^{\frac{b}{d}}{[\gcd(x,y)=1]} x=1∑day=1∑db[gcd(x,y)=1]
很容易发现:
[ gcd ( x , y ) = 1 ] = ∑ k ∣ gcd ( x , y ) μ ( k ) [\gcd(x,y)=1]=\sum\limits_{k|\gcd(x,y)}\mu(k) [gcd(x,y)=1]=k∣gcd(x,y)∑μ(k)
然后,开始化简:
∑ x = 1 a d ∑ y = 1 b d ∑ k ∣ gcd ( x , y ) μ ( k ) \sum\limits_{x=1}^{\frac{a}{d}}\sum\limits_{y=1}^{\frac{b}{d}}\sum\limits_{k|\gcd(x,y)}\mu(k) x=1∑day=1∑dbk∣gcd(x,y)∑μ(k)
拆掉 gcd \gcd gcd,枚举k
∑ x = 1 a d ∑ y = 1 b d ∑ k = 1 min ( a d , b d ) μ ( k ) [ k ∣ x ] [ k ∣ y ] \sum\limits_{x=1}^{\frac{a}{d}}\sum\limits_{y=1}^{\frac{b}{d}}\sum\limits_{k=1}^{\min(\frac{a}{d},\frac{b}{d})}\mu(k)[k|x][k|y] x=1∑day=1∑dbk=1∑min(da,db)μ(k)[k∣x][k∣y]
∑ k = 1 min ( a d , b d ) μ ( k ) ∑ x = 1 a d [ k ∣ x ] ∑ y = 1 b d [ k ∣ y ] \sum\limits_{k=1}^{\min(\frac{a}{d},\frac{b}{d})}\mu(k)\sum\limits_{x=1}^{\frac{a}{d}}[k|x]\sum\limits_{y=1}^{\frac{b}{d}}[k|y] k=1∑min(da,db)μ(k)x=1∑da[k∣x]y=1∑db[k∣y]
∑ k = 1 min ( a d , b d ) μ ( k ) ⌊ a d k ⌋ ⌊ b d k ⌋ \sum\limits_{k=1}^{\min(\frac{a}{d},\frac{b}{d})}\mu(k)\lfloor\frac{a}{dk}\rfloor\lfloor\frac{b}{dk}\rfloor k=1∑min(da,db)μ(k)⌊dka⌋⌊dkb⌋
很容易看出,最终结果就用莫比乌斯函数和数论分块计算就行了。
C
o
d
e
:
\tt Code:
Code:
#include <bits/stdc++.h>
#define int long long
using namespace std;
int N, M, D, cnt;
int Mu[50005], vis[50005], p[50005];
void Mobius() {
Mu[1] = 1;
for (int i = 2; i <= 50005; i++) {
if (!vis[i]) Mu[i] = -1, p[++cnt] = i;
for (int j = 1; j <= cnt && (int)i * p[j] <= 50005; j++) {
vis[i * p[j]] = true;
if (i % p[j] == 0) break;
Mu[i * p[j]] = -Mu[i];
}
Mu[i] += Mu[i - 1];
}
}
void Solve() {
int ans = 0;
scanf("%lld%lld%lld", &N, &M, &D);
if (N > M) swap(N, M);
N /= D, M /= D;
for (int l = 1, r; l <= N; l = r + 1) {
r = min((M / (M / l)), (N / (N / l)));
ans += (int)(Mu[r] - Mu[l - 1]) * (N / l) * (M / l);
}
printf("%lld\n", ans);
}
signed main() {
Mobius();
int T = 0;
scanf("%lld", &T);
while (T--) Solve();
return 0;
}
P2257 YY的GCD
题目描述:
神犇 YY 虐完数论后给
傻×kAc 出了一题
给定 N , M N, M N,M,求 1 ≤ x ≤ N 1 \leq x \leq N 1≤x≤N, 1 ≤ y ≤ M 1 \leq y \leq M 1≤y≤M 且 gcd ( x , y ) \gcd(x, y) gcd(x,y) 为质数的 ( x , y ) (x, y) (x,y) 有多少对。
输入格式:
第一行一个整数 T T T 表述数据组数。
接下来 T T T 行,每行两个正整数, N , M N, M N,M。
输出格式:
T T T 行,每行一个整数表示第 i i i 组数据的结果。
说明/提示:
T
=
1
0
4
,
N
,
M
≤
1
0
7
T=10^4,N, M \leq 10^7
T=104,N,M≤107
S
o
l
u
t
i
o
n
:
\tt Solution:
Solution:
这道题是前面那道题的升级版。
老规矩,我们先把题目化成人能看懂的样子:
∑ d ∈ p r i m e ∑ i = 1 x ∑ j = 1 y [ gcd ( x , y ) = d ] \sum\limits_{d\in{\tt prime}}\sum\limits_{i=1}^x\sum\limits_{j=1}^y[\gcd(x,y)=d] d∈prime∑i=1∑xj=1∑y[gcd(x,y)=d]
根据套路,我们先把 d d d提出来:
∑ d ∈ p r i m e ∑ i = 1 x d ∑ j = 1 y d [ gcd ( x , y ) = 1 ] \sum\limits_{d\in{\tt prime}}\sum\limits_{i=1}^{\frac{x}{d}}\sum\limits_{j=1}^{\frac{y}{d}}[\gcd(x,y)=1] d∈prime∑i=1∑dxj=1∑dy[gcd(x,y)=1]
然后转换成莫比乌斯函数的形式:
∑ d ∈ p r i m e ∑ i = 1 x d ∑ j = 1 y d ∑ k ∣ gcd ( x , y ) μ ( k ) \sum\limits_{d\in {\tt prime}}\sum\limits_{i=1}^{\frac{x}{d}}\sum\limits_{j=1}^{\frac{y}{d}}\sum\limits_{k|\gcd(x,y)}\mu(k) d∈prime∑i=1∑dxj=1∑dyk∣gcd(x,y)∑μ(k)
把 gcd \gcd gcd提出来,枚举 k k k:
∑ d ∈ p r i m e ∑ i = 1 x d ∑ j = 1 y d ∑ k = 1 min ( x d , y d ) μ ( k ) [ k ∣ x ] [ k ∣ y ] \sum\limits_{d\in {\tt prime}}\sum\limits_{i=1}^{\frac{x}{d}}\sum\limits_{j=1}^{\frac{y}{d}}\sum\limits_{k=1}^{\min(\frac{x}{d},\frac{y}{d})}\mu(k)[k|x][k|y] d∈prime∑i=1∑dxj=1∑dyk=1∑min(dx,dy)μ(k)[k∣x][k∣y]
各回各家:
∑ d ∈ p r i m e ∑ k = 1 min ( x d , y d ) μ ( k ) ∑ i = 1 x d [ k ∣ x ] ∑ j = 1 y d [ k ∣ y ] \sum\limits_{d\in {\tt prime}}\sum\limits_{k=1}^{\min(\frac{x}{d},\frac{y}{d})}\mu(k)\sum\limits_{i=1}^{\frac{x}{d}}[k|x]\sum\limits_{j=1}^{\frac{y}{d}} [k|y] d∈prime∑k=1∑min(dx,dy)μ(k)i=1∑dx[k∣x]j=1∑dy[k∣y]
后面的2个 Σ \Sigma Σ可以直接算:
∑ d ∈ p r i m e ∑ k = 1 min ( x d , y d ) μ ( k ) ⌊ x d k ⌋ ⌊ y d k ⌋ \sum\limits_{d\in{\tt prime}}\sum\limits_{k=1}^{\min(\frac{x}{d},\frac{y}{d})}\mu(k)\lfloor\frac{x}{dk}\rfloor\lfloor\frac{y}{dk}\rfloor d∈prime∑k=1∑min(dx,dy)μ(k)⌊dkx⌋⌊dky⌋
枚举 d k dk dk为 T T T:
∑ T = 1 min ( x , y ) ⌊ x T ⌋ ⌊ y T ⌋ ∑ t ∣ T , t ∈ p r i m e μ ( T t ) \sum\limits_{T=1}^{\min(x,y)}\lfloor\frac{x}{T}\rfloor\lfloor\frac{y}{T}\rfloor\sum\limits_{t|T,t\in{\tt prime}}\mu(\frac{T}{t}) T=1∑min(x,y)⌊Tx⌋⌊Ty⌋t∣T,t∈prime∑μ(tT)
令
f ( x ) = ∑ p ∣ x , p ∈ p r i m e μ ( x p ) f(x)=\sum\limits_{p|x,p\in{\tt prime}}\mu(\frac{x}{p}) f(x)=p∣x,p∈prime∑μ(px)
设
x
=
i
×
y
x =i\times y
x=i×y,
y
y
y是
x
x
x的最小质因子。
①当
x
∈
p
r
i
m
e
x\in {\tt prime}
x∈prime时,很容易得到:
f
(
x
)
=
μ
(
x
x
)
=
μ
(
1
)
=
1
f(x)=\mu(\frac{x}{x})=\mu(1)=1
f(x)=μ(xx)=μ(1)=1
②
i
m
o
d
y
=
0
i\mod y=0
imody=0时,即
x
x
x存在多个最小质因子:
- 当 i i i没有多个相同的质因子时,有且只有 p = y p=y p=y时 μ ( x p ) = μ ( i ) ≠ 0 \mu(\frac{x}{p})=\mu(i)\neq0 μ(px)=μ(i)=0。因为当 p ≠ y p\neq y p=y时, ∃ y > 1 且 y 2 ∣ x \exists y>1且y^2\vert x ∃y>1且y2∣x,
- 根据莫比乌斯函数的性质,很容易知道:这时的函数值为 0 0 0,所以 f ( x ) = μ ( i ) f(x)=\mu(i) f(x)=μ(i)。
- 当 i i i有多个相同的质因子时,对于任意 p p p,都有 μ ( x p ) = μ ( i ) = 0 \mu(\frac{x}{p})=\mu(i)=0 μ(px)=μ(i)=0。
- 所以当 i m o d y = 0 i\ mod\ y=0 i mod y=0时, f ( x ) = μ ( i ) f(x)=\mu(i) f(x)=μ(i)。
③ i m o d y ≠ 0 i\mod y \neq 0 imody=0时,即 x x x只存在一个最小质因子。
- f ( i ) = ∑ p ∈ p r i m e , p ∣ i μ ( i p ) , f ( x ) = ∑ p ∈ p r i m e , p ∣ x μ ( i × y p ) f(i)=\sum\limits_{p \in {\tt prime}, p\vert i}\mu(\frac{i}{p}),f(x)=\sum\limits_{p \in {\tt prime}, p\vert x}\mu(\frac{i\times y}{p}) f(i)=p∈prime,p∣i∑μ(pi),f(x)=p∈prime,p∣x∑μ(pi×y)
- 根据 μ \mu μ线性筛的过程,很容易知道 μ ( i × y p ) = − μ ( i p ) \mu(\frac{i\times y}{p})=-\mu(\frac{i}{p}) μ(pi×y)=−μ(pi),所以我们可以从 f ( x ) f(x) f(x)中找到任意一个属于 f ( i ) f(i) f(i)的项。
- 因此 f ( x ) f(x) f(x)比 f ( i ) f(i) f(i)多了一项 μ ( i × y y ) = μ ( i ) \mu(\frac{i\times y}{y}) = \mu(i) μ(yi×y)=μ(i)。
- 所以当 i m o d y ≠ 0 i\ mod\ y\neq0 i mod y=0时, f ( x ) = − f ( i ) + μ ( i ) f(x)=-f(i)+\mu(i) f(x)=−f(i)+μ(i)。
综上所述,我们得出:
f
(
x
)
=
{
μ
(
1
)
=
1
,
c
a
s
e
1
:
x
∈
p
r
i
m
e
μ
(
i
)
,
c
a
s
e
2
:
i
m
o
d
y
=
0.
−
f
(
i
)
+
μ
(
i
)
,
c
a
s
e
3
:
i
m
o
d
y
≠
0.
f(x)=\begin{cases}\mu(1)=1,&case\ 1:x\in {\tt prime}\\\mu(i),&case\ 2:i\mod y=0.\\-f(i)+\mu(i),&case\ 3:i\mod y\neq0.\end{cases}
f(x)=⎩⎪⎨⎪⎧μ(1)=1,μ(i),−f(i)+μ(i),case 1:x∈primecase 2:imody=0.case 3:imody=0.
所以,
A
n
s
=
∑
T
=
1
min
(
x
,
y
)
⌊
x
T
⌋
⌊
y
T
⌋
f
(
T
)
Ans=\sum\limits_{T=1}^{\min(x,y)}\lfloor\frac{x}{T}\rfloor\lfloor\frac{y}{T}\rfloor f(T)
Ans=T=1∑min(x,y)⌊Tx⌋⌊Ty⌋f(T)
我们只需要计算
f
(
T
)
f(T)
f(T)的前缀和与数论分块就行了。
C
o
d
e
:
Code:
Code:
#include <bits/stdc++.h>
#define int unsigned long long
using namespace std;
const int Maxn = 1e7 + 5, lnMaxn = Maxn / 16;
int N, M, T, cnt;
int f[Maxn], Mu[Maxn], p[lnMaxn];
bool vis[Maxn];
void Mobius() {
Mu[1] = vis[1] = 1;
for (int i = 2; i < Maxn; i++) {
if (!vis[i]) Mu[i] = -1, f[i] = 1, p[++cnt] = i; //case 1
for (int j = 1; j <= cnt && i * p[j] < Maxn; j++) {
vis[i * p[j]] = true;
if (i % p[j] == 0) {
f[i * p[j]] = Mu[i]; //case 2
break;
}
else {
f[i * p[j]] = -f[i] + Mu[i]; //case 3
}
Mu[i * p[j]] = -Mu[i];
}
f[i] += f[i - 1];
}
}
void Solve() {
int ans = 0;
scanf("%llu%llu", &N, &M);
if (N > M) swap(N, M);
for (int l = 1, r; l <= N; l = r + 1) {
r = min(N / (N / l), (M / (M / l)));
ans += (f[r] - f[l - 1]) * (N / l) * (M / l);
}
printf("%llu\n", ans);
}
signed main() {
scanf("%llu", &T);
Mobius();
while (T--) Solve();
return 0;
}
P3327 [SDOI2015]约数个数和
题目描述:
设 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}^md(ij) i=1∑nj=1∑md(ij).
输入格式:
输入文件包含多组测试数据。
第一行,一个整数 T T T,表示测试数据的组数。
接下来的 T T T 行,每行两个整数 n , m n,m n,m。
输出格式:
T 行,每行一个整数,表示你所求的答案。
说明/提示:
对于
100
%
100\%
100%的数据,
1
≤
T
,
n
,
m
≤
50000
1\le T,n,m \le 50000
1≤T,n,m≤50000
S
o
l
u
t
i
o
n
:
\tt Solution:
Solution:
首先我们得知道一个公式:
d
(
i
j
)
=
∑
x
∣
i
∑
y
∣
j
[
gcd
(
x
,
y
)
=
1
]
d(ij)=\sum\limits_{x\vert i}\sum\limits_{y\vert j}[\gcd(x,y)=1]
d(ij)=x∣i∑y∣j∑[gcd(x,y)=1]
然后进行化简:
∑ i = 1 n ∑ j = 1 m ∑ x ∣ i ∑ y ∣ j [ gcd ( x , y ) = 1 ] \sum\limits_{i=1}^n\sum\limits_{j=1}^m\sum\limits_{x\vert i}\sum\limits_{y\vert j}[\gcd(x,y)=1] i=1∑nj=1∑mx∣i∑y∣j∑[gcd(x,y)=1]
枚举 gcd ( x , y ) \gcd(x,y) gcd(x,y)的因数:
∑
i
=
1
n
∑
j
=
1
m
∑
x
∣
i
∑
y
∣
j
∑
d
∣
gcd
(
x
,
y
)
μ
(
d
)
\sum\limits_{i=1}^n\sum\limits_{j=1}^m\sum\limits_{x\vert i}\sum\limits_{y\vert j}\sum\limits_{d\vert\gcd(x,y)}\mu(d)
i=1∑nj=1∑mx∣i∑y∣j∑d∣gcd(x,y)∑μ(d)
∑
i
=
1
n
∑
j
=
1
m
∑
x
∣
i
∑
y
∣
j
∑
d
=
1
min
(
n
,
m
)
μ
(
d
)
[
d
∣
gcd
(
x
,
y
)
]
\sum\limits_{i=1}^n\sum\limits_{j=1}^m\sum\limits_{x\vert i}\sum\limits_{y\vert j}\sum\limits_{d=1}^{\min(n,m)}\mu(d)[d\vert\gcd(x,y)]
i=1∑nj=1∑mx∣i∑y∣j∑d=1∑min(n,m)μ(d)[d∣gcd(x,y)]
把莫比乌斯函数提到前面:
∑ d = 1 min ( n , m ) μ ( d ) ∑ i = 1 n ∑ j = 1 m ∑ x ∣ i ∑ y ∣ j [ d ∣ gcd ( x , y ) ] \sum\limits_{d=1}^{\min(n,m)}\mu(d)\sum\limits_{i=1}^n\sum\limits_{j=1}^m\sum\limits_{x\vert i}\sum\limits_{y\vert j}[d\vert\gcd(x,y)] d=1∑min(n,m)μ(d)i=1∑nj=1∑mx∣i∑y∣j∑[d∣gcd(x,y)]
把枚举 i , j i,j i,j的因子,改成枚举 x , y x,y x,y:
∑ d = 1 min ( n , m ) μ ( d ) ∑ x = 1 n ∑ y = 1 m [ d ∣ gcd ( x , y ) ] ⌊ n x ⌋ ⌊ n y ⌋ \sum\limits_{d=1}^{\min(n,m)}\mu(d)\sum\limits_{x=1}^n\sum\limits_{y=1}^m[d\vert\gcd(x,y)]\lfloor\frac{n}{x}\rfloor\lfloor\frac{n}{y}\rfloor d=1∑min(n,m)μ(d)x=1∑ny=1∑m[d∣gcd(x,y)]⌊xn⌋⌊yn⌋
把 d d d提出来,这样 gcd ( x , y ) \gcd(x,y) gcd(x,y)就可以消去了:
∑ d = 1 min ( n , m ) μ ( d ) ∑ x = 1 n d ∑ y = 1 m d ⌊ n d x ⌋ ⌊ m d y ⌋ \sum\limits_{d=1}^{\min(n,m)}\mu(d)\sum\limits_{x=1}^{\frac{n}{d}}\sum\limits_{y=1}^{\frac{m}{d}}\lfloor\frac{n}{dx}\rfloor\lfloor\frac{m}{dy}\rfloor d=1∑min(n,m)μ(d)x=1∑dny=1∑dm⌊dxn⌋⌊dym⌋
然后整理一下:
∑ d = 1 min ( n , m ) μ ( d ) ∑ x = 1 ⌊ n d ⌋ ⌊ n d x ⌋ ∑ y = 1 m d ⌊ ⌊ m d ⌋ y ⌋ \sum\limits_{d=1}^{\min(n,m)}\mu(d)\sum\limits_{x=1}^{\lfloor\frac{n}{d}\rfloor}\lfloor\frac{\frac{n}{d}}{x}\rfloor\sum\limits_{y=1}^{\frac{m}{d}}\lfloor\frac{\lfloor\frac{m}{d}\rfloor}{y}\rfloor d=1∑min(n,m)μ(d)x=1∑⌊dn⌋⌊xdn⌋y=1∑dm⌊y⌊dm⌋⌋
令:
f ( x ) = ∑ i = 1 x ⌊ x i ⌋ f(x)=\sum\limits_{i=1}^{x}\lfloor\frac{x}{i}\rfloor f(x)=i=1∑x⌊ix⌋
很容易发现:
f ( ⌊ n d ⌋ ) = ∑ x = 1 ⌊ n d ⌋ ⌊ ⌊ n d ⌋ x ⌋ f ( ⌊ m d ⌋ ) = ∑ x = 1 ⌊ m d ⌋ ⌊ ⌊ m d ⌋ x ⌋ f(\lfloor\frac{n}{d}\rfloor)=\sum\limits_{x=1}^{\lfloor\frac{n}{d}\rfloor}\lfloor\frac{\lfloor\frac{n}{d}\rfloor}{x}\rfloor \\\ f(\lfloor\frac{m}{d}\rfloor)=\sum\limits_{x=1}^{\lfloor\frac{m}{d}\rfloor}\lfloor\frac{\lfloor\frac{m}{d}\rfloor}{x}\rfloor f(⌊dn⌋)=x=1∑⌊dn⌋⌊x⌊dn⌋⌋ f(⌊dm⌋)=x=1∑⌊dm⌋⌊x⌊dm⌋⌋
所以:
A n s = ∑ d = 1 min ( n , m ) μ ( d ) ∗ f ( ⌊ n d ⌋ ) ∗ f ( ⌊ m d ⌋ ) Ans=\sum\limits_{d=1}^{\min(n,m)}\mu(d)*f(\lfloor\frac{n}{d}\rfloor)*f(\lfloor\frac{m}{d}\rfloor) Ans=d=1∑min(n,m)μ(d)∗f(⌊dn⌋)∗f(⌊dm⌋)
我们只需要处理出
μ
(
d
)
\mu(d)
μ(d)的前缀和与
f
(
x
)
f(x)
f(x)就行了。
C
o
d
e
:
\tt Code:
Code:
#include <bits/stdc++.h>
#define int long long
using namespace std;
int T, N, M;
int p[500100], Mu[500100], f[500100];
bool vis[500100];
void Mobius() {
Mu[1] = vis[1] = 1;
for (int i = 2; i <= 5e4; i++) { //处理μ(d)的前缀和
if (!vis[i]) Mu[i] = -1, p[++p[0]] = i;
for (int j = 1; j <= p[0] && i * p[j] <= 5e4; j++) {
vis[i * p[j]] = true;
if (i % p[j] == 0) break;
Mu[i * p[j]] = -Mu[i];
}
Mu[i] += Mu[i - 1];
}
for (int i = 1; i <= 5e4; i++) //处理f(x)
for (int l = 1, r; l <= i; l = r + 1) {
r = i / (i / l);
f[i] += (r - l + 1) * (i / l);
}
}
void Solve() {
int ans = 0;
scanf("%lld%lld", &N, &M);
if (N > M) swap(N, M);
for (int l = 1, r; l <= N; l = r + 1) {
r = min(N / (N / l), M / (M / l));
ans += (Mu[r] - Mu[l - 1]) * f[N / l] * f[M / l];
}
printf("%lld\n", ans);
}
signed main() {
scanf("%lld", &T);
Mobius();
while (T--) Solve();
return 0;
}