狄利克雷卷积
狄利克雷卷积
定义
数论函数
定义域为正整数的函数,称为数论函数。
常见数论函数:
| 函数符号 | 名称 | 定义 |
|---|---|---|
| ε ( n ) \varepsilon(n) ε(n) | 单位函数 | ε ( n ) = [ n = 1 ] \varepsilon(n)=[n=1] ε(n)=[n=1],即仅当 n = 1 n=1 n=1 时为 1 1 1,其余为 0 0 0 |
| 1 ( n ) \mathbf{1}(n) 1(n) | 常数函数 | 1 ( n ) = 1 \mathbf{1}(n)=1 1(n)=1,对任意正整数取值都为 1 1 1 |
| i d ( n ) \mathrm{id}(n) id(n) | 恒等函数 | i d ( n ) = n \mathrm{id}(n)=n id(n)=n |
| i d k ( n ) \mathrm{id}_k(n) idk(n) | 幂函数 | i d k ( n ) = n k \mathrm{id}_k(n)=n^k idk(n)=nk |
| μ ( n ) \mu(n) μ(n) | 莫比乌斯函数 | 按照因子个数取 ( − 1 ) k (-1)^k (−1)k 或 0 0 0 |
| φ ( n ) \varphi(n) φ(n) | 欧拉函数 | 1 ∼ n 1\sim n 1∼n 中与 n n n 互质的数的个数 |
| d ( n ) d(n) d(n) | 约数个数函数 | n n n 的正约数的个数 |
| σ ( n ) \sigma(n) σ(n) | 约数和函数 | n n n 的所有正约数的和 |
狄利克雷卷积
狄利克雷卷积就是在数论函数上的一种乘法运算,将复杂的交换求和过程转化成类似整式乘法的卷积运算,缩短公式的推导。
同时将欧拉函数,约数和函数通过简单的卷积运算得到。
狄利克雷卷积的定义公式
设 f , g f, g f,g 是两个数论函数,它们的狄利克雷卷积记作 f ∗ g f * g f∗g,结果仍是一个数论函数,其定义为:
( f ∗ g ) ( n ) = ∑ d ∣ n f ( d ) ⋅ g ( n d ) (f * g)(n) = \sum_{d \mid n} f(d) \cdot g\left(\frac{n}{d}\right) (f∗g)(n)=d∣n∑f(d)⋅g(dn)
性质
交换律:
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
单位函数:
单位函数 ε \varepsilon ε 是狄利克雷卷积的单位元,即对任意数论函数 f f f,有
f ∗ ε = f f * \varepsilon = f f∗ε=f
卷积逆元:
对于满足
f
(
1
)
≠
0
f(1) \neq 0
f(1)=0 的数论函数
f
f
f,存在唯一的函数
f
−
1
f^{-1}
f−1,使得
f
∗
f
−
1
=
ε
f * f^{-1} = \varepsilon
f∗f−1=ε
称
f
−
1
f^{-1}
f−1 为
f
f
f 的狄利克雷逆元。
特殊等式
- 1 ∗ μ = ε \mathbf{1} * \mu = \varepsilon 1∗μ=ε
- 1 ∗ 1 = d \mathbf{1} * \mathbf{1} = d 1∗1=d
- 1 ∗ i d = σ \mathbf{1} * id = \sigma 1∗id=σ
- 1 ∗ φ = i d \mathbf{1} * \varphi = id 1∗φ=id
- i d ∗ μ = φ id * \mu = \varphi id∗μ=φ
证明可以带入前面的狄利克雷卷积的定义式中。
所以前面的莫比乌斯反演的第一形式可以用这特殊等式轻松证明,证明如下:
定理:若
F
=
f
∗
1
F = f * \mathbf{1}
F=f∗1,即
F
(
n
)
=
∑
d
∣
n
f
(
d
)
F(n) = \sum_{d \mid n} f(d)
F(n)=d∣n∑f(d)
则有
f
(
n
)
=
∑
d
∣
n
F
(
d
)
⋅
μ
(
n
d
)
f(n) = \sum_{d \mid n} F(d) \cdot \mu\left(\frac{n}{d}\right)
f(n)=d∣n∑F(d)⋅μ(dn)
已知
F
=
f
∗
1
F = f * \mathbf{1}
F=f∗1,两边同时右乘
μ
\mu
μ:
F
∗
μ
=
(
f
∗
1
)
∗
μ
F * \mu = (f * \mathbf{1}) * \mu
F∗μ=(f∗1)∗μ
由结合律:
F
∗
μ
=
f
∗
(
1
∗
μ
)
F * \mu = f * (\mathbf{1} * \mu)
F∗μ=f∗(1∗μ)
代入
1
∗
μ
=
ε
\mathbf{1} * \mu = \varepsilon
1∗μ=ε:
F
∗
μ
=
f
∗
ε
=
f
F * \mu = f * \varepsilon = f
F∗μ=f∗ε=f
证毕。
积性定理
若 f f f 和 g g g 都是积性函数,则它们的狄利克雷卷积 f ∗ g f * g f∗g 也是积性函数。
证明:设
gcd
(
a
,
b
)
=
1
\gcd(a, b) = 1
gcd(a,b)=1,需证
(
f
∗
g
)
(
a
b
)
=
(
f
∗
g
)
(
a
)
⋅
(
f
∗
g
)
(
b
)
(f * g)(ab) = (f * g)(a) \cdot (f * g)(b)
(f∗g)(ab)=(f∗g)(a)⋅(f∗g)(b)
展开左边:
(
f
∗
g
)
(
a
b
)
=
∑
d
∣
a
b
f
(
d
)
g
(
a
b
/
d
)
(f * g)(ab) = \sum_{d \mid ab} f(d)g(ab/d)
(f∗g)(ab)=d∣ab∑f(d)g(ab/d)
由于 a , b a, b a,b 互质, a b ab ab 的每个约数 d d d 都可以唯一拆分为 d = d 1 d 2 d = d_1d_2 d=d1d2,其中 d 1 ∣ a d_1 \mid a d1∣a, d 2 ∣ b d_2 \mid b d2∣b,且 gcd ( d 1 , d 2 ) = 1 \gcd(d_1, d_2) = 1 gcd(d1,d2)=1。
代入得:
(
f
∗
g
)
(
a
b
)
=
∑
d
1
∣
a
∑
d
2
∣
b
f
(
d
1
d
2
)
g
(
a
d
1
⋅
b
d
2
)
(f * g)(ab) = \sum_{d_1 \mid a} \sum_{d_2 \mid b} f(d_1d_2)g\left(\frac{a}{d_1} \cdot \frac{b}{d_2}\right)
(f∗g)(ab)=d1∣a∑d2∣b∑f(d1d2)g(d1a⋅d2b)
=
∑
d
1
∣
a
∑
d
2
∣
b
f
(
d
1
)
f
(
d
2
)
g
(
a
/
d
1
)
g
(
b
/
d
2
)
= \sum_{d_1 \mid a} \sum_{d_2 \mid b} f(d_1)f(d_2)g(a/d_1)g(b/d_2)
=d1∣a∑d2∣b∑f(d1)f(d2)g(a/d1)g(b/d2)
=
(
∑
d
1
∣
a
f
(
d
1
)
g
(
a
/
d
1
)
)
⋅
(
∑
d
2
∣
b
f
(
d
2
)
g
(
b
/
d
2
)
)
= \left(\sum_{d_1 \mid a} f(d_1)g(a/d_1)\right) \cdot \left(\sum_{d_2 \mid b} f(d_2)g(b/d_2)\right)
=
d1∣a∑f(d1)g(a/d1)
⋅
d2∣b∑f(d2)g(b/d2)
=
(
f
∗
g
)
(
a
)
⋅
(
f
∗
g
)
(
b
)
= (f * g)(a) \cdot (f * g)(b)
=(f∗g)(a)⋅(f∗g)(b)
因为 1 \mathbf{1} 1, μ \mu μ, i d \mathrm{id} id 都是积性函数,所以由它们卷积得到的 d ( n ) d(n) d(n), σ ( n ) \sigma(n) σ(n), φ ( n ) \varphi(n) φ(n) 也都是积性函数,所以也可以用线性筛处理。
例题
CF1900D Small GCD
我们发现我们可以先将原数组排序。
那么答案就为:
A n s = ∑ i = 1 n ∑ j = i + 1 n ( n − j ) g c d ( a i , a j ) Ans = \sum\limits_{i=1}^n \sum\limits_{j=i+1}^n (n - j) gcd(a_i,a_j) Ans=i=1∑nj=i+1∑n(n−j)gcd(ai,aj)
利用欧拉反演公式替换 gcd \gcd gcd:
gcd ( a i , a j ) = ∑ d ∣ gcd ( a i , a j ) φ ( d ) = ∑ d ∣ a i , d ∣ a j φ ( d ) \gcd(a_i, a_j) = \sum_{d \mid \gcd(a_i, a_j)} \varphi(d) = \sum_{d \mid a_i , d \mid a_j} \varphi(d) gcd(ai,aj)=d∣gcd(ai,aj)∑φ(d)=d∣ai,d∣aj∑φ(d)
代入求和式,并交换求和顺序:
Ans = ∑ j = 2 n − 1 ( n − j ) ∑ d ∣ a j φ ( d ) ∑ i = 1 j − 1 [ d ∣ a i ] \text{Ans} = \sum_{j=2}^{n-1} (n-j) \sum_{d \mid a_j} \varphi(d) \sum_{i=1}^{j-1} [d \mid a_i] Ans=j=2∑n−1(n−j)d∣aj∑φ(d)i=1∑j−1[d∣ai]
观察式子最后的 ∑ i = 1 j − 1 [ d ∣ a i ] \sum_{i=1}^{j-1} [d \mid a_i] ∑i=1j−1[d∣ai],我们发现它的几何意义为在当前遍历到的 a j a_j aj 之前,有多少个数是 d d d 的倍数。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXX = 1e5 + 5, INF = 1e5 + 2;
int n, a[MAXX], num[MAXX], prime[MAXX], cnt, phi[MAXX], vis[MAXX], sum[MAXX], ans, t;
void init() {
num[0] = 1;
for(int i = 1; i <= INF; i++) num[i] = num[i - 1] * i;
phi[1] = 1;
for(int i = 2; i <= INF; i++) {
if(!vis[i]) {
prime[++cnt] = i;
phi[i] = i - 1;
}
for(int j = 1; j <= cnt && i * prime[j] <= INF; j++) {
vis[i * prime[j]] = 1;
if(i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
else {
phi[i * prime[j]] = phi[i] * phi[prime[j]];
}
}
}
for(int i = 1; i <= INF; i++) sum[i] = sum[i - 1] + phi[i];
}
void solve(){
cin >> n; ans = 0;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= INF; i++) sum[i] = 0;
sort(a + 1, a + 1 + n);
for(int j = 1; j <= n - 1; j++){
int num = 0;
for(int d = 1; d * d <= a[j]; d++){
if(a[j] % d == 0){
num += phi[d] * sum[d];
if(d * d != a[j]) num += phi[a[j] / d] * sum[a[j] / d];
}
}
ans = (ans + num * (n - j));
for(int d = 1; d * d <= a[j]; d++){
if(a[j] % d == 0){
sum[d]++;
if(d * d != a[j]) sum[a[j] / d]++;
}
}
}
cout << ans << '\n';
}
signed main(){
init();
cin >> t;
while(t--) solve();
return 0;
}
P1829 [集训队互测 2010] Crash的数字表格 / JZPTAB
由题得:
A
n
s
=
∑
i
=
1
n
∑
j
=
1
m
lcm
(
i
,
j
)
Ans = \sum_{i=1}^{n}\sum_{j=1}^{m}\operatorname{lcm}(i,j)
Ans=i=1∑nj=1∑mlcm(i,j)
将 lcm ( i , j ) = i ⋅ j gcd ( i , j ) \operatorname{lcm}(i,j)=\dfrac{i\cdot j}{\gcd(i,j)} lcm(i,j)=gcd(i,j)i⋅j,交换枚举顺序:
A n s = ∑ d = 1 n ∑ i = 1 n ∑ j = 1 m [ gcd ( i , j ) = d ] i ⋅ j d Ans=\sum_{d=1}^{n}\sum_{i=1}^{n}\sum_{j=1}^{m}[\gcd(i,j)=d]\frac{i\cdot j}{d} Ans=d=1∑ni=1∑nj=1∑m[gcd(i,j)=d]di⋅j
令 i = x d , j = y d i=xd,\ j=yd i=xd, j=yd 代入原式:
A n s = ∑ d = 1 n ∑ x = 1 ⌊ n / d ⌋ ∑ y = 1 ⌊ m / d ⌋ [ gcd ( x , y ) = 1 ] ⋅ x ⋅ y Ans=\sum_{d=1}^{n}\sum_{x=1}^{\lfloor n/d\rfloor}\sum_{y=1}^{\lfloor m/d\rfloor}[\gcd(x,y)=1]\cdot x\cdot y Ans=d=1∑nx=1∑⌊n/d⌋y=1∑⌊m/d⌋[gcd(x,y)=1]⋅x⋅y
所以设:
S ( N , M ) = ∑ x = 1 N ∑ y = 1 M [ gcd ( x , y ) = 1 ] ⋅ x ⋅ y S(N,M)=\sum_{x=1}^{N}\sum_{y=1}^{M}[\gcd(x,y)=1]\cdot x\cdot y S(N,M)=x=1∑Ny=1∑M[gcd(x,y)=1]⋅x⋅y
代入 [ gcd ( x , y ) = 1 ] = ∑ k ∣ x , k ∣ y μ ( k ) [\gcd(x,y)=1]=\sum_{k\mid x,\ k\mid y}\mu(k) [gcd(x,y)=1]=∑k∣x, k∣yμ(k),设 x = u k , y = v k x=uk,\ y=vk x=uk, y=vk:
S ( N , M ) = ∑ x = 1 N ∑ y = 1 M x y ∑ k ∣ x , k ∣ y μ ( k ) S(N,M)=\sum_{x=1}^{N}\sum_{y=1}^{M}xy\sum_{k\mid x,\ k\mid y}\mu(k) S(N,M)=x=1∑Ny=1∑Mxyk∣x, k∣y∑μ(k)
= ∑ k = 1 min ( N , M ) μ ( k ) ∑ u = 1 ⌊ N / k ⌋ ∑ v = 1 ⌊ M / k ⌋ ( u k ) ⋅ ( v k ) =\sum_{k=1}^{\min(N,M)}\mu(k)\sum_{u=1}^{\lfloor N/k\rfloor}\sum_{v=1}^{\lfloor M/k\rfloor}(uk)\cdot(vk) =k=1∑min(N,M)μ(k)u=1∑⌊N/k⌋v=1∑⌊M/k⌋(uk)⋅(vk)
= ∑ k = 1 min ( N , M ) μ ( k ) ⋅ k 2 ( ∑ u = 1 ⌊ N / k ⌋ u ) ( ∑ v = 1 ⌊ M / k ⌋ v ) =\sum_{k=1}^{\min(N,M)}\mu(k)\cdot k^2\left(\sum_{u=1}^{\lfloor N/k\rfloor}u\right)\left(\sum_{v=1}^{\lfloor M/k\rfloor}v\right) =k=1∑min(N,M)μ(k)⋅k2 u=1∑⌊N/k⌋u v=1∑⌊M/k⌋v
( ∑ u = 1 ⌊ N / k ⌋ u ) ( ∑ v = 1 ⌊ M / k ⌋ v ) \left(\sum_{u=1}^{\lfloor N/k\rfloor}u\right)\left(\sum_{v=1}^{\lfloor M/k\rfloor}v\right) u=1∑⌊N/k⌋u v=1∑⌊M/k⌋v 后面的这个可以用整除分块解决。
所以:
A n s = ∑ d = 1 min ( n , m ) d ∑ k = 1 min ( ⌊ n / d ⌋ , ⌊ m / d ⌋ ) μ ( k ) ⋅ k 2 ( ∑ u = 1 ⌊ N / k ⌋ u ) ( ∑ v = 1 ⌊ M / k ⌋ v ) Ans=\sum_{d=1}^{\min(n,m)}d\sum_{k=1}^{\min(\lfloor n/d\rfloor,\lfloor m/d\rfloor)}\mu(k)\cdot k^2\left(\sum_{u=1}^{\lfloor N/k\rfloor}u\right)\left(\sum_{v=1}^{\lfloor M/k\rfloor}v\right) Ans=d=1∑min(n,m)dk=1∑min(⌊n/d⌋,⌊m/d⌋)μ(k)⋅k2 u=1∑⌊N/k⌋u v=1∑⌊M/k⌋v
令 T = d k T=dk T=dk 代入:
A n s = ∑ T = 1 min ( n , m ) ( ∑ u = 1 ⌊ N / k ⌋ u ) ( ∑ v = 1 ⌊ M / k ⌋ v ) ∑ k ∣ T T k ⋅ μ ( k ) ⋅ k 2 Ans=\sum_{T=1}^{\min(n,m)}\left(\sum_{u=1}^{\lfloor N/k\rfloor}u\right)\left(\sum_{v=1}^{\lfloor M/k\rfloor}v\right)\sum_{k\mid T}\frac{T}{k}\cdot\mu(k)\cdot k^2 Ans=T=1∑min(n,m) u=1∑⌊N/k⌋u v=1∑⌊M/k⌋v k∣T∑kT⋅μ(k)⋅k2
虽然现在这个可以直接做了,但是我们考虑继续优化,我们观察后面的部分。
∑ k ∣ T T k ⋅ μ ( k ) ⋅ k 2 = T ∑ k ∣ T k ⋅ μ ( k ) \sum_{k\mid T}\frac{T}{k}\cdot\mu(k)\cdot k^2 = T\sum_{k\mid T}k\cdot\mu(k) k∣T∑kT⋅μ(k)⋅k2=Tk∣T∑k⋅μ(k)
又因为 ∑ k ∣ T k μ ( k ) \sum\limits_{k\mid T}k\mu(k) k∣T∑kμ(k) 是积性函数 ( id ⋅ μ ) (\operatorname{id}\cdot\mu) (id⋅μ) 与 1 \mathbf{1} 1 的卷积,因此 T ∑ k ∣ T k ⋅ μ ( k ) T\sum_{k\mid T}k\cdot\mu(k) Tk∣T∑k⋅μ(k) 依然是积性函数,用线性筛处理即可。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXX = 1e7 + 5, M = 20101009, INF = 1e7 + 2;
int n, m, p[MAXX], prime[MAXX], cnt, sum[MAXX], ans, vis[MAXX];
void init(){
p[1] = 1;
for(int i = 2; i <= INF; i++) {
if(!vis[i]) {
prime[++cnt] = i;
p[i] = ((1 - i) * i % M + M) % M;
}
for(int j = 1; j <= cnt && i * prime[j] <= INF; j++) {
vis[i * prime[j]] = 1;
if(i % prime[j] == 0) {
p[i * prime[j]] = p[i] * prime[j] % M;
break;
}else p[i * prime[j]] = p[i] * p[prime[j]] % M;
}
}
for(int i = 1; i <= INF; i++) sum[i] = (sum[i - 1] + p[i]) % M;
}
signed main(){
init();
cin >> n >> m;
for(int l = 1, r; l <= min(n, m); l = r + 1){
r = min(n / (n / l), m / (m / l));
ans = (ans + ((n / l) * (n / l + 1) / 2) % M * ((m / l) * (m / l + 1) / 2 % M) % M * ((sum[r] - sum[l - 1] + M) % M) % M) % M;
}
cout << ans << '\n';
return 0;
}
综合题目练习
abc020D
这道题是一个典型的套路题。
我们先将 l c m lcm lcm 转换:
A n s = ∑ i = 1 n i k g c d ( i , k ) Ans = \sum_{i=1}^n \frac{ik}{gcd(i,k)} Ans=i=1∑ngcd(i,k)ik
= ∑ i = 1 n ∑ d = 1 i i k d [ g c d ( i , k / d ) = 1 ] = \sum_{i=1}^n \sum_{d=1}^i \frac{ik}{d}[gcd(i,k/d) = 1] =i=1∑nd=1∑idik[gcd(i,k/d)=1]
= ∑ i = 1 n ∑ d = 1 i i k d ∑ g ∣ g c d ( i , k / d ) μ ( g ) =\sum_{i=1}^n \sum_{d=1}^i \frac{ik}{d} \sum_{g| gcd(i,k/d)} \mu(g) =i=1∑nd=1∑idikg∣gcd(i,k/d)∑μ(g)
= k ∑ d ∣ k ∑ i = 1 ⌊ n / d ⌋ i ∑ g ∣ g c d ( i , k / d ) μ ( g ) =k\sum_{d|k} \sum_{i=1}^{\lfloor n/d \rfloor} i \sum_{g| gcd(i,k/d)} \mu(g) =kd∣k∑i=1∑⌊n/d⌋ig∣gcd(i,k/d)∑μ(g)
= k ∑ d ∣ k ∑ g ∣ k / d μ ( g ) ∑ i = 1 ⌊ n / d g ⌋ i g =k\sum_{d|k}\sum_{g| k/d} \mu(g) \sum_{i=1}^{\lfloor n/dg \rfloor} ig =kd∣k∑g∣k/d∑μ(g)i=1∑⌊n/dg⌋ig
然后预处理 k k k 的因数即可AC此题
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXX = 1e5 + 5, M = 1e9 + 7;
int n, k, num[MAXX], cnt, ans, sum[MAXX];
int mu(int n){
int res = 1;
for(int i = 2; i * i <= n; i++){
if(n % i == 0){
int zrr = 0;
while(n % i == 0) n /= i, zrr++;
if(zrr >= 2) return 0;
res = -res;
}
}
if(n != 1) res = -res;
return res;
}
__int128_t SUM(__int128_t x){
return (1 + x) * x / 2 % M;
}
signed main(){
cin >> n >> k;
for(int i = 1; i * i <= k; i++){
if(k % i == 0){
num[++cnt] = i;
if(i * i != k) num[++cnt] = (k / i);
}
}
sort(num + 1, num + 1 + cnt);
for(int i = 1; i <= cnt; i++) sum[i] = mu(num[i]);
for(int d = 1; d <= cnt; d++){
int res = 0;
for(int g = 1; g <= cnt; g++){
if((k / num[d]) % num[g] != 0) continue;
res = (res + sum[g] * num[g] % M * SUM(n / num[d] / num[g]) % M + M) % M;
}
ans = (ans + res) % M;
}
cout << ans * k % M;
return 0;
}
P2231
由于裴蜀定理可以知道当为合法情况的时候仅当 g c d { a 1 , a 2 , a 3 … a n } = 1 gcd\{a_1,a_2,a_3 \dots a_n\} = 1 gcd{a1,a2,a3…an}=1
然后我们直接大力莫反:
Ans = ∑ 1 ≤ a 1 ≤ M ⋯ ∑ 1 ≤ a N ≤ M [ gcd ( a 1 , … , a N , M ) = 1 ] \text{Ans} = \sum_{1 \le a_1 \le M} \cdots \sum_{1 \le a_N \le M} [\gcd(a_1, \ldots, a_N, M) = 1] Ans=1≤a1≤M∑⋯1≤aN≤M∑[gcd(a1,…,aN,M)=1]
= ∑ d ∣ M μ ( d ) ( ∑ 1 ≤ a 1 ≤ M , d ∣ a 1 1 ) ⋯ ( ∑ 1 ≤ a N ≤ M , d ∣ a N 1 ) = \sum_{d \mid M} \mu(d) \left( \sum_{1 \le a_1 \le M,\, d \mid a_1} 1 \right) \cdots \left( \sum_{1 \le a_N \le M,\, d \mid a_N} 1 \right) =d∣M∑μ(d) 1≤a1≤M,d∣a1∑1 ⋯ 1≤aN≤M,d∣aN∑1
= ∑ d ∣ M μ ( d ) ( M d ) N = \sum_{d \mid M} \mu(d) \left( \frac{M}{d} \right)^N =d∣M∑μ(d)(dM)N
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n, m, cnt, ans;
int qpow(int a, int b){
int res = 1;
while(b){
if(b & 1) res = res * a;
a = a * a, b /= 2;
}
return res;
}
int mu(int n){
int res = 1;
for(int i = 2; i * i <= n; i++){
if(n % i == 0){
int zrr = 0;
while(n % i == 0) n /= i, zrr++;
if(zrr >= 2) return 0;
res = -res;
}
}
if(n != 1) res = -res;
return res;
}
signed main(){
cin >> n >> m;
for(int i = 1; i * i <= m; i++){
if(m % i == 0){
ans += mu(i) * qpow(m / i, n);
if(i * i != m) ans += mu(m / i) * qpow(i, n);
}
}
cout << ans << '\n';
return 0;
}
CF235E
前置知识:
d ( i j ) = ∑ x ∣ i ∑ y ∣ j [ g c d ( x , y ) = 1 ] d(ij)=\sum\limits_{x|i} \sum\limits_{y|j}[gcd(x,y)=1] d(ij)=x∣i∑y∣j∑[gcd(x,y)=1]
有公式可转换:
d ( i ⋅ j ⋅ k ) = ∑ u ∣ i ∑ v ∣ j ∑ w ∣ k [ gcd ( u , v ) = 1 ] [ gcd ( v , w ) = 1 ] [ gcd ( w , u ) = 1 ] d(i \cdot j \cdot k) = \sum_{u|i} \sum_{v|j} \sum_{w|k} [\gcd(u, v) = 1][\gcd(v, w) = 1][\gcd(w, u) = 1] d(i⋅j⋅k)=u∣i∑v∣j∑w∣k∑[gcd(u,v)=1][gcd(v,w)=1][gcd(w,u)=1]
然后我们暴力莫反:
[ gcd ( u , v ) = 1 ] = ∑ x ∣ u , x ∣ v μ ( x ) [\gcd(u, v) = 1] = \sum_{x|u, x|v} \mu(x) [gcd(u,v)=1]=x∣u,x∣v∑μ(x)
[ gcd ( v , w ) = 1 ] = ∑ y ∣ v , y ∣ w μ ( y ) [\gcd(v, w) = 1] = \sum_{y|v, y|w} \mu(y) [gcd(v,w)=1]=y∣v,y∣w∑μ(y)
[ gcd ( w , u ) = 1 ] = ∑ z ∣ w , z ∣ u μ ( z ) [\gcd(w, u) = 1] = \sum_{z|w, z|u} \mu(z) [gcd(w,u)=1]=z∣w,z∣u∑μ(z)
将其带入,交换求和顺序:
Ans = ∑ x = 1 a μ ( x ) ∑ y = 1 b μ ( y ) ∑ z = 1 c μ ( z ) ( ∑ x ∣ u , z ∣ u ⌊ a u ⌋ ) ( ∑ x ∣ v , y ∣ v ⌊ b v ⌋ ) ( ∑ y ∣ w , z ∣ w ⌊ c w ⌋ ) \text{Ans} = \sum_{x=1}^{a} \mu(x) \sum_{y=1}^{b} \mu(y) \sum_{z=1}^{c} \mu(z) \left( \sum_{x|u, z|u} \left\lfloor \frac{a}{u} \right\rfloor \right) \left( \sum_{x|v, y|v} \left\lfloor \frac{b}{v} \right\rfloor \right) \left( \sum_{y|w, z|w} \left\lfloor \frac{c}{w} \right\rfloor \right) Ans=x=1∑aμ(x)y=1∑bμ(y)z=1∑cμ(z) x∣u,z∣u∑⌊ua⌋ x∣v,y∣v∑⌊vb⌋ y∣w,z∣w∑⌊wc⌋
我们设:
S ( N , M ) = ∑ M ∣ k ⌊ N k ⌋ = ∑ t = 1 ⌊ N / M ⌋ ⌊ N M ⋅ t ⌋ S(N, M) = \sum_{M|k} \left\lfloor \frac{N}{k} \right\rfloor = \sum_{t=1}^{\lfloor N/M \rfloor} \left\lfloor \frac{N}{M \cdot t} \right\rfloor S(N,M)=M∣k∑⌊kN⌋=t=1∑⌊N/M⌋⌊M⋅tN⌋
又:
∑ lcm ( x , z ) ∣ u ⌊ a u ⌋ = S ( a , lcm ( x , z ) ) \sum_{\text{lcm}(x,z) \mid u} \left\lfloor \frac{a}{u} \right\rfloor = S(a, \text{lcm}(x, z)) lcm(x,z)∣u∑⌊ua⌋=S(a,lcm(x,z))
∑ lcm ( x , y ) ∣ v ⌊ b v ⌋ = S ( b , lcm ( x , y ) ) \sum_{\text{lcm}(x,y) \mid v} \left\lfloor \frac{b}{v} \right\rfloor = S(b, \text{lcm}(x, y)) lcm(x,y)∣v∑⌊vb⌋=S(b,lcm(x,y))
∑ lcm ( y , z ) ∣ w ⌊ c w ⌋ = S ( c , lcm ( y , z ) ) \sum_{\text{lcm}(y,z) \mid w} \left\lfloor \frac{c}{w} \right\rfloor = S(c, \text{lcm}(y, z)) lcm(y,z)∣w∑⌊wc⌋=S(c,lcm(y,z))
然后我们暴力处理,对于
μ
=
0
\mu = 0
μ=0
的时候直接结束循环,并且与处理
S
S
S 和
l
c
m
lcm
lcm 即可AC此题。
将其整理:
Ans = ∑ x = 1 a μ ( x ) ∑ y = 1 b μ ( y ) ∑ z = 1 c μ ( z ) ⋅ S ( a , lcm ( x , z ) ) ⋅ S ( b , lcm ( x , y ) ) ⋅ S ( c , lcm ( y , z ) ) \text{Ans} = \sum_{x=1}^{a} \mu(x) \sum_{y=1}^{b} \mu(y) \sum_{z=1}^{c} \mu(z) \cdot S(a, \text{lcm}(x, z)) \cdot S(b, \text{lcm}(x, y)) \cdot S(c, \text{lcm}(y, z)) Ans=x=1∑aμ(x)y=1∑bμ(y)z=1∑cμ(z)⋅S(a,lcm(x,z))⋅S(b,lcm(x,y))⋅S(c,lcm(y,z))
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXX = 2e3 + 5, INF = 2e3 + 2, M = 1073741824;
int a, b, c, mu[MAXX], vis[MAXX], s[MAXX][MAXX], LCM[MAXX][MAXX], ans;
vector<int> p;
void init(){
for(int n = 1; n <= INF; n++){
for(int m = 1; m <= n; m++){
for(int k = 1; k <= n / m; k++) s[n][m] = (s[n][m] + n / (m * k)) % M;
}
}
for(int i = 1; i <= INF; i++){
for(int j = 1; j <= INF; j++) LCM[i][j] = i * j / __gcd(i, j);
}
mu[1] = 1;
for(int i = 2; i <= INF; i++){
if(!vis[i]) p.push_back(i), mu[i] = -1;
for(int j : p){
if(i * j > INF) break;
vis[i * j] = 1, mu[i * j] = -mu[i];
if(i % j == 0){ mu[i * j] = 0; break; }
}
}
}
signed main(){
init();
cin >> a >> b >> c;
for(int x = 1; x <= a; x++){
if(mu[x] == 0) continue;
for(int y = 1; y <= b; y++){
if(mu[y] == 0) continue;
if(LCM[x][y] > a) continue;
for(int z = 1; z <= c; z++){
if(mu[z] == 0) continue;
if(LCM[y][z] > b) continue;
if(LCM[x][z] > c) continue;
if(mu[x] * mu[y] * mu[z] == 1) ans = (ans + s[a][LCM[x][y]] * s[b][LCM[z][y]] % M * s[c][LCM[x][z]] % M) % M;
else ans = (ans - s[a][LCM[x][y]] * s[b][LCM[z][y]] % M * s[c][LCM[x][z]] % M + M) % M;
}
}
}
cout << ans << "\n";
return 0;
}
P10584
前置知识,重要恒等式
μ 2 ( d ) = ∑ k 2 ∣ d μ ( k ) \mu^2(d) = \sum_{k^2 \mid d} \mu(k) μ2(d)=k2∣d∑μ(k)
任意正整数 x x x 表示为 x = d ⋅ y 2 x = d \cdot y^2 x=d⋅y2,我们称 (d) 为“平方因子自由数”。
则 i ⋅ j = ( d 1 x 2 ) ⋅ ( d 2 y 2 ) = d 1 d 2 ( x y ) 2 i \cdot j = (d_1 x^2) \cdot (d_2 y^2) = d_1 d_2 (xy)^2 i⋅j=(d1x2)⋅(d2y2)=d1d2(xy)2 是完全平方数,当且仅当 d 1 = d 2 d_1 = d_2 d1=d2。
所以设 i = d ⋅ x 2 i = d \cdot x^2 i=d⋅x2, j = d ⋅ y 2 j = d \cdot y^2 j=d⋅y2(其中 μ 2 ( d ) = 1 \mu^2(d) = 1 μ2(d)=1):
- 1 ≤ d ⋅ x 2 ≤ n ⟹ 1 ≤ x ≤ ⌊ n d ⌋ 1 \leq d \cdot x^2 \leq n \implies 1 \leq x \leq \left\lfloor \sqrt{\frac{n}{d}} \right\rfloor 1≤d⋅x2≤n⟹1≤x≤⌊dn⌋
- 1 ≤ d ⋅ y 2 ≤ m ⟹ 1 ≤ y ≤ ⌊ m d ⌋ 1 \leq d \cdot y^2 \leq m \implies 1 \leq y \leq \left\lfloor \sqrt{\frac{m}{d}} \right\rfloor 1≤d⋅y2≤m⟹1≤y≤⌊dm⌋
原式可转化为对 d d d 的求和:
Ans = ∑ d = 1 min ( n , m ) μ 2 ( d ) ⌊ n d ⌋ ⌊ m d ⌋ \text{Ans} = \sum_{d=1}^{\min(n,m)} \mu^2(d) \left\lfloor \sqrt{\frac{n}{d}} \right\rfloor \left\lfloor \sqrt{\frac{m}{d}} \right\rfloor Ans=d=1∑min(n,m)μ2(d)⌊dn⌋⌊dm⌋
我们直接将公式代入:
Ans
=
∑
d
=
1
min
(
n
,
m
)
(
∑
k
2
∣
d
μ
(
k
)
)
⌊
n
d
⌋
⌊
m
d
⌋
\text{Ans} = \sum_{d=1}^{\min(n,m)} \left( \sum_{k^2|d} \mu(k) \right) \left\lfloor \sqrt{\frac{n}{d}} \right\rfloor \left\lfloor \sqrt{\frac{m}{d}} \right\rfloor
Ans=d=1∑min(n,m)
k2∣d∑μ(k)
⌊dn⌋⌊dm⌋
= ∑ k = 1 ⌊ min ( n , m ) ⌋ μ ( k ) ∑ t = 1 ⌊ min ( n , m ) / k 2 ⌋ ⌊ n k 2 t ⌋ ⌊ m k 2 t ⌋ = \sum_{k=1}^{\lfloor \sqrt{\min(n,m)} \rfloor} \mu(k) \sum_{t=1}^{\left\lfloor \min(n,m)/k^2 \right\rfloor} \left\lfloor \sqrt{\frac{n}{k^2 t}} \right\rfloor \left\lfloor \sqrt{\frac{m}{k^2 t}} \right\rfloor =k=1∑⌊min(n,m)⌋μ(k)t=1∑⌊min(n,m)/k2⌋⌊k2tn⌋⌊k2tm⌋
我们设:
h ( A , B ) = ∑ t = 1 min ( A , B ) ⌊ A t ⌋ ⌊ B t ⌋ h(A, B) = \sum_{t=1}^{\min(A, B)} \left\lfloor \sqrt{\frac{A}{t}} \right\rfloor \left\lfloor \sqrt{\frac{B}{t}} \right\rfloor h(A,B)=t=1∑min(A,B)⌊tA⌋⌊tB⌋
所以最终结果就为:
Ans = ∑ k = 1 ⌊ min ( n , m ) ⌋ μ ( k ) ⋅ h ( ⌊ n k 2 ⌋ , ⌊ m k 2 ⌋ ) \text{Ans} = \sum_{k=1}^{\lfloor \sqrt{\min(n,m)} \rfloor} \mu(k) \cdot h\left(\left\lfloor \frac{n}{k^2} \right\rfloor, \left\lfloor \frac{m}{k^2} \right\rfloor\right) Ans=k=1∑⌊min(n,m)⌋μ(k)⋅h(⌊k2n⌋,⌊k2m⌋)
然后我们直接用二次分块加上线性筛预处理即可。
代码读者自写不难。
做题技巧
对于 g c d ( i , j ) = 1 gcd(i,j)=1 gcd(i,j)=1 或者 g c d ( i , j ) gcd(i,j) gcd(i,j) 在分母的情况我们要有先用莫比乌斯反演。
对于 g c d ( i , j ) gcd(i,j) gcd(i,j) 的普通情况我们先考虑欧拉反演公式。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐
所有评论(0)