1:整除
1.1:整除的性质 1
对于 ∀ a , b , c ∈ Z ∀ a , b , c ∈ Z ,有:
⌊ a b c ⌋ = ⎢ ⎢
⎢
⎢
⎢ ⎣ ⌊ a b ⌋ c ⎥ ⎥
⎥
⎥
⎥ ⎦ ⌊ a b c ⌋ = ⌊ ⌊ a b ⌋ c ⌋
证明
设 a b = ⌊ a b ⌋ + r a b = ⌊ a b ⌋ + r ,其中 0 ≤ r < 1 0 ≤ r < 1 ,则:
⌊ a b c ⌋ = ⌊ a b ⋅ 1 c ⌋ = ⌊ 1 c ( ⌊ a b ⌋ + r ) ⌋ = ⎢ ⎢
⎢
⎢
⎢ ⎣ ⌊ a b ⌋ c + r c ⎥ ⎥
⎥
⎥
⎥ ⎦ = ⎢ ⎢
⎢
⎢
⎢ ⎣ ⌊ a b ⌋ c ⎥ ⎥
⎥
⎥
⎥ ⎦ ⌊ a b c ⌋ = ⌊ a b ⋅ 1 c ⌋ = ⌊ 1 c ( ⌊ a b ⌋ + r ) ⌋ = ⌊ ⌊ a b ⌋ c + r c ⌋ = ⌊ ⌊ a b ⌋ c ⌋
Q.E.D
1.2:整除的性质 2
给出一个正整数 n n ,对于正整数 d ( 1 ≤ d ≤ n ) d ( 1 ≤ d ≤ n ) ,⌊ n d ⌋ ⌊ n d ⌋ 的取值不超过 2 √ n 2 n 种。
证明
可以分类讨论:
若 d ≤ √ n d ≤ n ,因为 d d 的取值不超过 √ n n 种,显然 ⌊ n d ⌋ ⌊ n d ⌋ 的取值不超过 √ n n 种。
若 d > √ n d > n ,则 ⌊ n d ⌋ ≤ √ n ⌊ n d ⌋ ≤ n ,故 ⌊ n d ⌋ ⌊ n d ⌋ 的取值不超过 √ n n 种。
综上所述,⌊ n d ⌋ ⌊ n d ⌋ 的取值不超过 2 √ n 2 n 种,Q.E.D
1.3:整除分块
给出一个正整数 n n ,请你求出:
n ∑ i = 1 ⌊ n i ⌋ ∑ i = 1 n ⌊ n i ⌋
其中 1 ≤ n ≤ 10 9 1 ≤ n ≤ 10 9 。
分析
观察到函数 f ( x ) = n x f ( x ) = n x 在区间 ( 0 , + ∞ ) ( 0 , + ∞ ) 上单调递减。
所以,对于函数 g ( x ) = ⌊ n x ⌋ g ( x ) = ⌊ n x ⌋ 的任意一个函数值,令 g ( x ) g ( x ) 取到该值的所有自变量 x x 组成一段连续的区间。
根据「1.2:引理 2」,我们知道这样的区间个数也是 O ( √ n ) O ( n ) 级别的。
对于一段满足 g ( x ) g ( x ) 均相等的区间,我们可以直接得出该区间里的所有 x x 对答案的贡献。那现在的关键在于如何得到这些区间。
考虑任意一个 i ( 1 ≤ i ≤ n ) i ( 1 ≤ i ≤ n ) ,我们现在要找到一个最大的 j ( i ≤ j ≤ n ) j ( i ≤ j ≤ n ) ,使得 ⌊ n i ⌋ = ⌊ n j ⌋ ⌊ n i ⌋ = ⌊ n j ⌋ 。结论:j = ⌊ n ⌊ n i ⌋ ⌋ j = ⌊ n ⌊ n i ⌋ ⌋ 。
证明
第一步,证明其合法性(i ≤ j ≤ n i ≤ j ≤ n )。
⌊ n i ⌋ ≤ n i ⟹ ⌊ n ⌊ n i ⌋ ⌋ ≥ ⌊ n n i ⌋ = i ⟹ i ≤ ⌊ n ⌊ n i ⌋ ⌋ = j ⌊ n i ⌋ ≤ n i ⟹ ⌊ n ⌊ n i ⌋ ⌋ ≥ ⌊ n n i ⌋ = i ⟹ i ≤ ⌊ n ⌊ n i ⌋ ⌋ = j
第二步,证明其为最大值。
考虑任意一个满足 ⌊ n i ⌋ = ⌊ n j ⌋ ⌊ n i ⌋ = ⌊ n j ⌋ 的 j j :
⌊ n i ⌋ = ⌊ n j ⌋ ⟹ ⌊ n i ⌋ ≤ n j < ⌊ n i ⌋ + 1 ⟹ 1 ⌊ n i ⌋ + 1 < j n ≤ 1 ⌊ n i ⌋ ⟹ n ⌊ n i ⌋ + 1 < j ≤ n ⌊ n i ⌋ ⌊ n i ⌋ = ⌊ n j ⌋ ⟹ ⌊ n i ⌋ ≤ n j < ⌊ n i ⌋ + 1 ⟹ 1 ⌊ n i ⌋ + 1 < j n ≤ 1 ⌊ n i ⌋ ⟹ n ⌊ n i ⌋ + 1 < j ≤ n ⌊ n i ⌋
因为 j ∈ Z j ∈ Z ,故 j max = ⌊ n ⌊ n i ⌋ ⌋ j max = ⌊ n ⌊ n i ⌋ ⌋ 。
Q.E.D
实现
根据上述结论,我们就有了找出这 O ( √ n ) O ( n ) 个区间的方法。直接套结论做即可,时间复杂度是 O ( √ n ) O ( n ) 的。
view code for (int x = 1 , nx; x <= n; x = nx + 1 ) {
nx = n / (n / x);
ans += 1ll * (nx - x + 1 ) * (n / x);
}
1.4:多维整除分块
给出两个正整数 n , m n , m ,请你求出:
min ( n , m ) ∑ i = 1 ⌊ n i ⌋ ⌊ m i ⌋ ∑ i = 1 min ( n , m ) ⌊ n i ⌋ ⌊ m i ⌋
其中 1 ≤ n , m ≤ 10 9 1 ≤ n , m ≤ 10 9 。
分析
上式的乘积项包含两个取整分式。
考虑任意一个 i i ,我们现在要找到一个最大的 j j ,使得 ⌊ n i ⌋ = ⌊ n j ⌋ ⌊ n i ⌋ = ⌊ n j ⌋ 且 ⌊ m i ⌋ = ⌊ m j ⌋ ⌊ m i ⌋ = ⌊ m j ⌋ 。易证:j = min { ⌊ n ⌊ n i ⌋ ⌋ , ⌊ m ⌊ m i ⌋ ⌋ } j = min { ⌊ n ⌊ n i ⌋ ⌋ , ⌊ m ⌊ m i ⌋ ⌋ } 。
扩展到多维也是一样的道理。
2:积性函数
2.1:积性函数的定义
若数论函数 f ( n ) f ( n ) 满足:对于任意互质正整数 x , y x , y ,都有 f ( x y ) = f ( x ) f ( y ) f ( x y ) = f ( x ) f ( y ) 。则 f ( n ) f ( n ) 为积性函数 。
若数论函数 f ( n ) f ( n ) 满足:对于任意正整数 x , y x , y ,都有 f ( x y ) = f ( x ) f ( y ) f ( x y ) = f ( x ) f ( y ) 。则 f ( n ) f ( n ) 为完全积性函数 。
2.2:积性函数的简单性质
对于任意积性函数 f ( x ) f ( x ) ,都有 f ( 1 ) = 1 f ( 1 ) = 1 。
对于任意积性函数 f ( x ) , g ( x ) f ( x ) , g ( x ) ,则以下的 h ( x ) h ( x ) 也均为积性函数:
h ( x ) = f ( x p ) h ( x ) = f p ( x ) h ( x ) = f ( x ) g ( x ) h ( x ) = ∑ d | x f ( d ) g ( x d ) h ( x ) = f ( x p ) h ( x ) = f p ( x ) h ( x ) = f ( x ) g ( x ) h ( x ) = ∑ d | x f ( d ) g ( x d )
将 x x 分解质因数,若 f ( x ) f ( x ) 为积性函数,则 f ( x ) = m ∏ i = 1 f ( p c i i ) f ( x ) = ∏ i = 1 m f ( p i c i ) 。
2.3:常见积性函数
ϵ ( n ) = [ n = 1 ] ϵ ( n ) = [ n = 1 ]
ID k ( n ) = n k ID k ( n ) = n k
1 ( n ) = 1 1 ( n ) = 1
σ k ( n ) = ∑ d | n d k σ k ( n ) = ∑ d | n d k
φ ( n ) = n m ∏ i = 1 ( 1 − 1 p i ) φ ( n ) = n ∏ i = 1 m ( 1 − 1 p i )
μ ( n ) = ⎧ ⎨ ⎩ 0 ∃ i ∈ [ 1 , m ] , c i > 1 1 m ≡ 0 ( mod 2 ) , ∀ i ∈ [ 1 , m ] , c i = 1 − 1 m ≡ 1 ( mod 2 ) , ∀ i ∈ [ 1 , m ] , c i = 1 μ ( n ) = { 0 ∃ i ∈ [ 1 , m ] , c i > 1 1 m ≡ 0 ( mod 2 ) , ∀ i ∈ [ 1 , m ] , c i = 1 − 1 m ≡ 1 ( mod 2 ) , ∀ i ∈ [ 1 , m ] , c i = 1
3:Dirichlet 卷积
3.1:Dirichlet 卷积的定义
定义两个数论函数 f , g f , g 的 Dirichlet 卷积为:
( f ∗ g ) ( n ) = ∑ d | n f ( d ) ⋅ g ( n d ) ( f ∗ g ) ( n ) = ∑ d | n f ( d ) ⋅ g ( n d )
3.2:Dirichlet 卷积的性质
交换律: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 + f ∗ h f ∗ ( g + h ) = f ∗ g + f ∗ h 。
单位元:f ∗ ϵ = f f ∗ ϵ = f ,因此 ϵ ϵ 也被叫做 Dirichlet 卷积单位元。
3.3:常见 Dirichlet 卷积式
3.3.1:式 1
ϵ = μ ∗ 1 ⟺ ∑ d | n μ ( d ) = ϵ ( n ) ϵ = μ ∗ 1 ⟺ ∑ d | n μ ( d ) = ϵ ( n )
证明
不难看出关于 n n 的函数 f ( n ) = ∑ d ∣ n μ ( d ) f ( n ) = ∑ d ∣ n μ ( d ) 是个积性函数。
f ( n ) = m ∏ i = 1 f ( p c i i ) = m ∏ i = 1 ⎛ ⎜ ⎝ ∑ d | p c i i μ ( d ) ⎞ ⎟ ⎠ = m ∏ i = 1 ( c i ∑ j = 0 μ ( p j i ) ) = m ∏ i = 1 ( μ ( 1 ) + μ ( p i ) ) = 0 f ( n ) = ∏ i = 1 m f ( p i c i ) = ∏ i = 1 m ( ∑ d | p i c i μ ( d ) ) = ∏ i = 1 m ( ∑ j = 0 c i μ ( p i j ) ) = ∏ i = 1 m ( μ ( 1 ) + μ ( p i ) ) = 0
综上所述,f ( n ) = ∑ d | n μ ( d ) = [ n = 1 ] f ( n ) = ∑ d | n μ ( d ) = [ n = 1 ] ,Q.E.D
3.3.2:式 2
ID = φ ∗ 1 ⟺ ∑ d | n φ ( d ) = n ID = φ ∗ 1 ⟺ ∑ d | n φ ( d ) = n
证明
不难看出关于 n n 的函数 f ( n ) = ∑ d | n φ ( d ) f ( n ) = ∑ d | n φ ( d ) 是个积性函数。
当 n = 1 n = 1 时,显然有 f ( 1 ) = 1 f ( 1 ) = 1 。
当 n > 1 n > 1 时,将 n n 质因数分解,得:
f ( n ) = m ∏ i = 1 f ( p c i i ) = m ∏ i = 1 ⎛ ⎜ ⎝ ∑ d | p c i i φ ( d ) ⎞ ⎟ ⎠ = m ∏ i = 1 ( c i ∑ j = 0 φ ( p j i ) ) = m ∏ i = 1 ( 1 + c i ∑ j = 1 φ ( p j i ) ) = m ∏ i = 1 ( 1 + c i ∑ j = 1 ( p j i − p j − 1 i ) ) = m ∏ i = 1 p c i i = n f ( n ) = ∏ i = 1 m f ( p i c i ) = ∏ i = 1 m ( ∑ d | p i c i φ ( d ) ) = ∏ i = 1 m ( ∑ j = 0 c i φ ( p i j ) ) = ∏ i = 1 m ( 1 + ∑ j = 1 c i φ ( p i j ) ) = ∏ i = 1 m ( 1 + ∑ j = 1 c i ( p i j − p i j − 1 ) ) = ∏ i = 1 m p i c i = n
综上所述,f ( n ) = ∑ d | n φ ( d ) = n f ( n ) = ∑ d | n φ ( d ) = n ,Q.E.D
3.3.3:式 3
φ = μ ∗ ID ⟺ φ ( n ) = ∑ d | n d ⋅ μ ( n d ) φ = μ ∗ ID ⟺ φ ( n ) = ∑ d | n d ⋅ μ ( n d )
证明
φ ∗ 1 = ID ⟹ φ ∗ 1 ∗ μ = μ ∗ ID ⟹ φ ∗ ϵ = μ ∗ ID ⟹ φ = μ ∗ ID φ ∗ 1 = ID ⟹ φ ∗ 1 ∗ μ = μ ∗ ID ⟹ φ ∗ ϵ = μ ∗ ID ⟹ φ = μ ∗ ID
Q.E.D
4:线性筛
线性筛,也叫 Euler 筛。可以在线性时间内筛出 1 ∼ n 1 ∼ n 里的所有质数。相信大家都会。
4.1:线性筛筛积性函数
线性筛可以在线性时间内筛出大部分积性函数的前 n n 项的函数值。
一般地,对于积性函数 f ( x ) f ( x ) ,若 f ( p c ) f ( p c ) 的值便于分析。则该函数的前 n n 项的函数值可以被线性筛筛出来。
我们要多维护一个数组 low i low i 表示:若 i i 的最小质因子为 p 1 p 1 ,其次数为 c 1 c 1 ,则 low i = p c 1 1 low i = p 1 c 1 。
在线性筛的过程中,有特殊的两点:
若当前遇到了一个质数 p p ,则将 f ( p ) , f ( p 2 ) , f ( p 3 ) , ⋯ , f ( p c ) f ( p ) , f ( p 2 ) , f ( p 3 ) , ⋯ , f ( p c ) 都计算出来。
在计算至少包含两个质因子的 i i 对应的函数值时,由积性函数定义得 f ( i ) = f ( i low i ) ⋅ f ( low i ) f ( i ) = f ( i low i ) ⋅ f ( low i ) 。
这样就可以在线性时间内筛出一个积性函数的前 n n 项了。对于一些简单的积性函数(例如 φ , μ φ , μ )就有更简单的筛法,不一定需要维护 low i low i 。
4.1.1:线性筛筛欧拉函数
设 p p 为质数,若 p ∣ n p ∣ n 且 p 2 ∣ n p 2 ∣ n ,则 φ ( n ) = φ ( n p ) ⋅ p φ ( n ) = φ ( n p ) ⋅ p 。
设 p p 为质数,若 p ∣ n p ∣ n 且 p 2 ∤ n p 2 ∤ n ,则 φ ( n ) = φ ( n p ) ⋅ ( p − 1 ) φ ( n ) = φ ( n p ) ⋅ ( p − 1 ) 。
view code const int SZ = 1e6 ;
int pClock, prime[SZ + 10 ], fac[SZ + 10 ];
int phi[SZ + 10 ];
void sieve (int N) {
phi[1 ] = 1 ;
for (int i = 2 ; i <= N; i ++) {
if (!fac[i]) fac[i] = i, prime[++ pClock] = i, phi[i] = i - 1 ;
for (int j = 1 ; j <= pClock; j ++) {
if (prime[j] > fac[i] || prime[j] > N / i) break ;
fac[i * prime[j]] = prime[j];
phi[i * prime[j]] = phi[i] * (i % prime[j] ? prime[j] - 1 : prime[j]);
}
}
}
4.1.2:线性筛筛莫比乌斯函数
设 p p 为质数,若 p ∣ n p ∣ n 且 p 2 ∣ n p 2 ∣ n ,则 μ ( n ) = 0 μ ( n ) = 0 。
设 p p 为质数,若 p ∣ n p ∣ n 且 p 2 ∤ n p 2 ∤ n ,则 μ ( n ) = − μ ( n p ) μ ( n ) = − μ ( n p ) 。
view code const int SZ = 1e6 ;
int pClock, prime[SZ + 10 ], fac[SZ + 10 ];
int mu[SZ + 10 ];
void sieve (int N) {
mu[1 ] = 1 ;
for (int i = 2 ; i <= N; i ++) {
if (!fac[i]) fac[i] = i, prime[++ pClock] = i, mu[i] = -1 ;
for (int j = 1 ; j <= pClock; j ++) {
if (prime[j] > fac[i] || prime[j] > N / i) break ;
fac[i * prime[j]] = prime[j];
mu[i * prime[j]] = mu[i] * (i % prime[j] ? -1 : 0 );
}
}
}
4.1.3:线性筛筛各种积性函数
根据积性函数的特殊性质。利用 low i low i 数组。可以在线性时间内筛出大部分积性函数的前 n n 项的函数值。
请读者好好品味这段代码。
view code const int SZ = 1e6 ;
int pClock, prime[SZ + 10 ], low[SZ + 10 ];
int f[SZ + 10 ];
void sieve (int N) {
f[1 ] = 1 ;
for (int i = 2 ; i <= N; i ++) {
if (!low[i]) {
prime[++ pClock] = i;
long long x = i;
int c = 1 ;
while (x <= N) {
low[x] = x;
x *= i, c ++;
}
}
for (int j = 1 ; j <= pClock; j ++) {
if (prime[j] > N / i) break ;
if (i % prime[j] == 0 )
low[i * prime[j]] = low[i] * prime[j];
else
low[i * prime[j]] = prime[j];
int num = i * prime[j];
f[num] = f[num / low[num]] * f[low[num]];
if (i % prime[j] == 0 ) break ;
}
}
}
4.2:例题选讲
4.2.1:【日常训练】挺好序列
Description
定义一个长度为 n n 的挺好序列 a 1 , a 2 , ⋯ , a n a 1 , a 2 , ⋯ , a n ,满足:对于 ∀ i ∈ [ 1 , n ] ∀ i ∈ [ 1 , n ] ,都有 a i | A a i | A 。
定义一个长度为 n n 的挺好序列 a 1 , a 2 , ⋯ , a n a 1 , a 2 , ⋯ , a n 的价值为 gcd ( a 1 , a 2 , ⋯ , a n , B ) gcd ( a 1 , a 2 , ⋯ , a n , B ) ,其中 B B 为定值。
给出三个正整数 n , m , B n , m , B 。定义 f ( x ) f ( x ) 为 A = x A = x 时所有挺好序列的价值和。请你求出:
m ∑ i = 1 f ( i ) ∑ i = 1 m f ( i )
答案对 998244353 998244353 取模。
数据范围:1 ≤ n ≤ 10 18 1 ≤ n ≤ 10 18 ,1 ≤ m ≤ 2 × 10 7 1 ≤ m ≤ 2 × 10 7 ,1 ≤ B ≤ 10 18 1 ≤ B ≤ 10 18 。
时空限制:3000 ms / 512 MiB 3000 ms / 512 MiB 。
Solution
结论
f ( x ) f ( x ) 是积性函数。
证明
考虑任意互质的正整数对 x , y x , y 。
设序列 a 1 , a 2 , ⋯ , a n a 1 , a 2 , ⋯ , a n 是 A = x A = x 时的某个挺好序列,设序列 b 1 , b 2 , ⋯ , b n b 1 , b 2 , ⋯ , b n 是 A = y A = y 时的某个挺好序列。
考虑生成序列 c 1 , c 2 , ⋯ , c n c 1 , c 2 , ⋯ , c n ,其中 c i = a i b i c i = a i b i ,显然该序列是 A = x y A = x y 时的某个挺好序列。
关注序列 c c 的价值。因为 x , y x , y 互质,所以 a i , b i a i , b i 也一定互质。在唯一分解 角度下观察,显然有:
gcd ( a 1 , a 2 , ⋯ , a n , B ) ⋅ gcd ( b 1 , b 2 , ⋯ , b n , B ) = gcd ( c 1 , c 2 , ⋯ , c n , B ) gcd ( a 1 , a 2 , ⋯ , a n , B ) ⋅ gcd ( b 1 , b 2 , ⋯ , b n , B ) = gcd ( c 1 , c 2 , ⋯ , c n , B )
故序列 c c 的价值为序列 a , b a , b 的价值之积。
回到积性函数的讨论上。f ( x ) ⋅ f ( y ) f ( x ) ⋅ f ( y ) 的每一项,相当于是从 f ( x ) f ( x ) 与 f ( y ) f ( y ) 各选一项的乘积。故 f ( x ) ⋅ f ( y ) f ( x ) ⋅ f ( y ) 是 A = x y A = x y 时所有挺好序列的价值和。
所以 f ( x y ) = f ( x ) ⋅ f ( y ) f ( x y ) = f ( x ) ⋅ f ( y ) ,所以 f ( x ) f ( x ) 为积性函数。
Q.E.D
注意到 1 ≤ m ≤ 2 × 10 7 1 ≤ m ≤ 2 × 10 7 ,可以考虑线性筛。按照上文「4.1.3:线性筛筛积性函数」的内容。现在要对于任意一个质数 p p ,如何求出 f ( p c ) f ( p c ) 。
对于一个质数 p p ,令 d d 为满足 p x ∣ B p x ∣ B 的最大的 x x 。可以简单分类讨论一下,不难得出:
f ( p c ) = c ∑ i = 0 p i ⋅ [ ( c − i + 1 ) n − ( c − i ) n ] f ( p c ) = ∑ i = 0 c p i ⋅ [ ( c − i + 1 ) n − ( c − i ) n ]
f ( p c ) = p d ⋅ ( c − d + 1 ) n + d − 1 ∑ i = 0 p i ⋅ [ ( c − i + 1 ) n − ( c − i ) n ] f ( p c ) = p d ⋅ ( c − d + 1 ) n + ∑ i = 0 d − 1 p i ⋅ [ ( c − i + 1 ) n − ( c − i ) n ]
求出 f ( p ) , f ( p 2 ) , ⋯ , f ( p c ) f ( p ) , f ( p 2 ) , ⋯ , f ( p c ) 后,灵活运用线性筛即可求出 f ( x ) f ( x ) 的前 m m 项,那么 m ∑ i = 1 f ( i ) ∑ i = 1 m f ( i ) 就直接算即可。
view code #include <cstdio>
#include <cstring>
#include <algorithm>
typedef long long s64;
int qpow (int a, s64 b, int p) {
int ans = 1 ;
for (; b; b >>= 1 ) {
if (b & 1 ) ans = 1ll * ans * a % p;
a = 1ll * a * a % p;
}
return ans;
}
const int SZ = 2e7 ;
const int mod = 998244353 ;
void add (int &x, const int &y) {
x += y;
if (x >= mod) x -= mod;
}
void dec (int &x, const int &y) {
x -= y;
if (x < 0 ) x += mod;
}
s64 n, B;
int m;
int pClock, prime[SZ + 10 ], low[SZ + 10 ];
int f[SZ + 10 ];
int get_top (int p) {
int num = B, cnt = 0 ;
while (num % p == 0 ) num /= p, cnt ++;
return cnt;
}
int power[100 ];
void sieve (int N) {
for (int i = 1 ; i < 100 ; i ++) power[i] = qpow(i, n, mod);
f[1 ] = 1 ;
for (int i = 2 ; i <= N; i ++) {
if (!low[i]) {
prime[++ pClock] = i;
int d = get_top(i);
s64 x = i;
int c = 1 ;
while (x <= N) {
low[x] = x;
if (c <= d) {
for (int j = 0 , g = 1 ; j <= c; j ++, g = 1ll * g * i % mod) {
int rate = power[c - j + 1 ]; dec(rate, power[c - j]);
add(f[x], 1ll * g * rate % mod);
}
} else {
int g = 1 ;
for (int j = 0 ; j < d; j ++, g = 1ll * g * i % mod) {
int rate = power[c - j + 1 ]; dec(rate, power[c - j]);
add(f[x], 1ll * g * rate % mod);
}
add(f[x], 1ll * g * power[c - d + 1 ] % mod);
}
x *= i, c ++;
}
}
for (int j = 1 ; j <= pClock; j ++) {
if (prime[j] > N / i) break ;
if (i % prime[j] == 0 )
low[i * prime[j]] = low[i] * prime[j];
else
low[i * prime[j]] = prime[j];
int num = i * prime[j];
f[num] = 1ll * f[num / low[num]] * f[low[num]] % mod;
if (i % prime[j] == 0 ) break ;
}
}
}
int main () {
scanf ("%lld%d%lld" , &n, &m, &B);
sieve(m);
int ans = 0 ;
for (int i = 1 ; i <= m; i ++) add(ans, f[i]);
printf ("%d\n" , ans);
return 0 ;
}
5:莫比乌斯反演
已知两个数论函数 f , g f , g 满足:
f ( n ) = ∑ d ∣ n g ( d ) f ( n ) = ∑ d ∣ n g ( d )
则:
g ( n ) = ∑ d ∣ n f ( d ) ∗ μ ( n d ) g ( n ) = ∑ d ∣ n f ( d ) ∗ μ ( n d )
证明
已知条件等价于:
f = g ∗ 1 f = g ∗ 1
两边同卷 μ μ 可得:
g ∗ ϵ = f ∗ μ g = f ∗ μ g ∗ ϵ = f ∗ μ g = f ∗ μ
QED。
5.1:例题选讲
5.1.1:经典问题
Description
给出一个正整数 n n ,求有多少个长度为 n n ,循环节长度也恰好为 n n 的小写字符串。
数据范围:1 ≤ n ≤ 10 9 1 ≤ n ≤ 10 9 。
Solution
设长度为 n n 的小写字符串有 f ( n ) f ( n ) 个;设长度为 n n ,循环节长度也恰好为 n n 的小写字符串有 g ( n ) g ( n ) 个。
显然有:
f ( n ) = 26 n f ( n ) = 26 n
以及:
f ( n ) = ∑ d ∣ n g ( n ) f ( n ) = ∑ d ∣ n g ( n )
根据莫比乌斯反演,可得:
g ( n ) = ∑ d | n 26 d ∗ μ ( n d ) g ( n ) = ∑ d | n 26 d ∗ μ ( n d )
5.1.2:【Luogu P2522】「HAOI2011」Problem b
Luogu P2522 。
Description
给出五个正整数 a , b , c , d , k a , b , c , d , k ,请你求出:
∑ a ≤ i ≤ b ∑ c ≤ j ≤ d [ gcd ( i , j ) = k ] ∑ a ≤ i ≤ b ∑ c ≤ j ≤ d [ gcd ( i , j ) = k ]
共 T T 组询问。
数据范围:1 ≤ T , k ≤ 5 × 10 4 1 ≤ T , k ≤ 5 × 10 4 ,1 ≤ a ≤ b ≤ 5 × 10 4 1 ≤ a ≤ b ≤ 5 × 10 4 ,1 ≤ c ≤ d ≤ 5 × 10 4 1 ≤ c ≤ d ≤ 5 × 10 4 。
时空限制:2500 m s / 250 M i B 2500 m s / 250 M i B 。
Solution
记 calc ( n , m ) calc ( n , m ) 为:
n ∑ i = 1 m ∑ j = 1 [ gcd ( i , j ) = k ] ∑ i = 1 n ∑ j = 1 m [ gcd ( i , j ) = k ]
简单容斥可得,答案为:
calc ( b , d ) − calc ( a − 1 , d ) − calc ( b , c − 1 ) + calc ( a − 1 , c − 1 ) calc ( b , d ) − calc ( a − 1 , d ) − calc ( b , c − 1 ) + calc ( a − 1 , c − 1 )
考虑这样一个 calc ( n , m ) calc ( n , m ) 要怎么求,注意到 gcd ( i , j ) = k gcd ( i , j ) = k 与 gcd ( i k , j k ) = 1 gcd ( i k , j k ) = 1 是等价的,故原式化为:
⌊ n k ⌋ ∑ i = 1 ⌊ m k ⌋ ∑ j = 1 [ gcd ( i , j ) = 1 ] ⌊ n k ⌋ ∑ i = 1 ⌊ m k ⌋ ∑ j = 1 ϵ ( gcd ( i , j ) ) ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ m k ⌋ [ gcd ( i , j ) = 1 ] ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ m k ⌋ ϵ ( gcd ( i , j ) )
利用 ϵ = μ ∗ 1 ϵ = μ ∗ 1 反演,得:
⌊ n k ⌋ ∑ i = 1 ⌊ m k ⌋ ∑ j = 1 ∑ d ∣ gcd ( i , j ) μ ( d ) ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ m k ⌋ ∑ d ∣ gcd ( i , j ) μ ( d )
交换枚举顺序,考虑先枚举 d d 。要使得 d ∣ gcd ( i , j ) d ∣ gcd ( i , j ) ,只需要让 d ∣ i d ∣ i 且 d ∣ j d ∣ j 即可,故答案化为:
min ( ⌊ n k ⌋ , ⌊ m k ⌋ ) ∑ d = 1 μ ( d ) ⋅ ⌊ n k d ⌋ ⋅ ⌊ m k d ⌋ ∑ d = 1 min ( ⌊ n k ⌋ , ⌊ m k ⌋ ) μ ( d ) ⋅ ⌊ n k d ⌋ ⋅ ⌊ m k d ⌋
上式就比较好处理了。线性筛筛出莫比乌斯函数,求一遍莫比乌斯函数的前缀和,然后直接上数论分块。
实现上,可以先令 n ← ⌊ n k ⌋ , m ← ⌊ m k ⌋ n ← ⌊ n k ⌋ , m ← ⌊ m k ⌋ ,这样就比较好做了。
时间复杂度 O ( N + T √ N ) O ( N + T N ) ,其中 N N 表示输入数据上界。
5.1.3:【Luogu P1829】「国家集训队」Crash 的数字表格
Luogu P1829 。
Description
给出两个正整数 n , m n , m ,请你求出:
n ∑ i = 1 m ∑ j = 1 lcm ( i , j ) ∑ i = 1 n ∑ j = 1 m lcm ( i , j )
答案对 20101009 20101009 取模。
数据范围:1 ≤ n , m ≤ 10 7 1 ≤ n , m ≤ 10 7 。
时空限制:2000 m s / 500 M i B 2000 m s / 500 M i B 。
Solution
不难发现原式为:
n ∑ i = 1 m ∑ j = 1 i × j gcd ( i , j ) ∑ i = 1 n ∑ j = 1 m i × j gcd ( i , j )
令 d = gcd ( i , j ) d = gcd ( i , j ) ,考虑交换枚举顺序:
min ( n , m ) ∑ d = 1 1 d ⋅ n ∑ d ∣ i m ∑ d ∣ j [ gcd ( i , j ) = d ] i × j ∑ d = 1 min ( n , m ) 1 d ⋅ ∑ d ∣ i n ∑ d ∣ j m [ gcd ( i , j ) = d ] i × j
将 i i 和 j j 中的 d d 提取出来,得:
min ( n , m ) ∑ d = 1 d ⋅ ⌊ n d ⌋ ∑ i = 1 ⌊ m d ⌋ ∑ j = 1 [ gcd ( i , j ) = 1 ] i × j ∑ d = 1 min ( n , m ) d ⋅ ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ [ gcd ( i , j ) = 1 ] i × j
记:
F ( n , m ) = n ∑ i = 1 m ∑ j = 1 [ gcd ( i , j ) = 1 ] i × j F ( n , m ) = ∑ i = 1 n ∑ j = 1 m [ gcd ( i , j ) = 1 ] i × j
考虑化简 F ( n , m ) F ( n , m ) :
F ( n , m ) = n ∑ i = 1 m ∑ j = 1 i × j × ∑ p ∣ gcd ( i , j ) μ ( p ) = min ( n , m ) ∑ p = 1 μ ( p ) ⋅ p 2 ⋅ ⌊ n p ⌋ ∑ i = 1 ⌊ m p ⌋ ∑ j = 1 i × j F ( n , m ) = ∑ i = 1 n ∑ j = 1 m i × j × ∑ p ∣ gcd ( i , j ) μ ( p ) = ∑ p = 1 min ( n , m ) μ ( p ) ⋅ p 2 ⋅ ∑ i = 1 ⌊ n p ⌋ ∑ j = 1 ⌊ m p ⌋ i × j
记:
g ( n , m ) = n ∑ i = 1 m ∑ j = 1 i ⋅ j = n ∑ i = 1 i ⋅ m ∑ j = 1 j = n ( n + 1 ) 2 ⋅ m ( m + 1 ) 2 g ( n , m ) = ∑ i = 1 n ∑ j = 1 m i ⋅ j = ∑ i = 1 n i ⋅ ∑ j = 1 m j = n ( n + 1 ) 2 ⋅ m ( m + 1 ) 2
则:
F ( n , m ) = min ( n , m ) ∑ p = 1 μ ( p ) ⋅ p 2 ⋅ g ( ⌊ n p ⌋ , ⌊ m p ⌋ ) F ( n , m ) = ∑ p = 1 min ( n , m ) μ ( p ) ⋅ p 2 ⋅ g ( ⌊ n p ⌋ , ⌊ m p ⌋ )
可以线性筛一下,然后数论分块。当 n , m n , m 同阶时,计算 F ( n , m ) F ( n , m ) 是 O ( √ n ) O ( n ) 的。
回到本题,可得答案为:
min ( n , m ) ∑ d = 1 d ⋅ F ( ⌊ n d ⌋ , ⌊ m d ⌋ ) ∑ d = 1 min ( n , m ) d ⋅ F ( ⌊ n d ⌋ , ⌊ m d ⌋ )
然后这个式子也可以数论分块做,本质上是一个数论分块套数论分块。
线性筛的复杂度是 Θ ( n ) Θ ( n ) 的。数论分块套数论分块的复杂度是 O ( n 3 4 ) O ( n 3 4 ) 。
于是这题就这样做完了。
关于「数论分块套数论分块」复杂度的证明
原问题中最后计算答案的式子是一个二维数论分块套二维数论分块,看起来不太爽。我们把它替换成一个一维数论分块套一维数论分块,大概是这样:
n ∑ d = 1 d ⋅ F ( ⌊ n d ⌋ ) ∑ d = 1 n d ⋅ F ( ⌊ n d ⌋ )
其中,计算 F ( n ) F ( n ) 的复杂度是 O ( √ n ) O ( n ) 的。考虑证明上式的复杂度。
可以分类讨论一下:
当 d ≤ √ n d ≤ n 时,最劣的情况是每一个 ⌊ n d ⌋ ⌊ n d ⌋ 互不相同,故此部分对复杂度的贡献为:
√ n ∑ i = 1 O ( √ n i ) ∑ i = 1 n O ( n i )
当 d > √ n d > n 时,注意到 ⌊ n d ⌋ ⌊ n d ⌋ 的值会均会落在区间 [ 1 , √ n ] [ 1 , n ] 中,最劣的情况是 ⌊ n d ⌋ ⌊ n d ⌋ 的值将 [ 1 , √ n ] [ 1 , n ] 里的所有数都取过一遍,故此部分对复杂度的贡献为:
√ n ∑ i = 1 O ( √ i ) ∑ i = 1 n O ( i )
简单积分近似一下:
√ n ∑ i = 1 O ( √ i ) + √ n ∑ i = 1 O ( √ n i ) ≈ O ⎛ ⎜ ⎝ ∫ n 1 2 0 [ x 1 2 + ( n x ) 1 2 ] dx ⎞ ⎟ ⎠ ∑ i = 1 n O ( i ) + ∑ i = 1 n O ( n i ) ≈ O ( ∫ 0 n 1 2 [ x 1 2 + ( n x ) 1 2 ] dx )
根据微积分基本定理,设 H ( x ) = 2 3 x 3 2 + n 1 2 ⋅ 2 x 1 2 H ( x ) = 2 3 x 3 2 + n 1 2 ⋅ 2 x 1 2 ,有 H ′ ( x ) = x 1 2 + ( n x ) 1 2 H ′ ( x ) = x 1 2 + ( n x ) 1 2 。则:
∫ n 1 2 0 [ x 1 2 + ( n x ) 1 2 ] dx = H ( n 1 2 ) − H ( 0 ) = 8 3 n 3 4 ∫ 0 n 1 2 [ x 1 2 + ( n x ) 1 2 ] dx = H ( n 1 2 ) − H ( 0 ) = 8 3 n 3 4
故数论分块套数论分块的复杂度是 O ( n 3 4 ) O ( n 3 4 ) 的。
5.1.4:【Luogu P2257】YY 的 GCD
Luogu P2257 。
Description
给出两个正整数 n , m n , m ,请你求出满足 1 ≤ i ≤ n 1 ≤ i ≤ n 且 1 ≤ j ≤ m 1 ≤ j ≤ m 的所有数对 ( i , j ) ( i , j ) 中,满足 gcd ( i , j ) gcd ( i , j ) 为质数的数对有多少个。
共 Q Q 组数据。
数据范围:1 ≤ Q ≤ 10 4 1 ≤ Q ≤ 10 4 ,1 ≤ n , m ≤ 10 8 1 ≤ n , m ≤ 10 8 。
时空限制:4000 m s / 500 M i B 4000 m s / 500 M i B 。
Solution
为了方便叙述,设质数集为 P P 。
注意到答案为:
∑ p ∈ P n ∑ i = 1 m ∑ j = 1 [ gcd ( i , j ) = p ] ∑ p ∈ P ⌊ n p ⌋ ∑ i = 1 ⌊ m p ⌋ ∑ j = 1 [ gcd ( i , j ) = 1 ] ∑ p ∈ P ⌊ n p ⌋ ∑ i = 1 ⌊ m p ⌋ ∑ j = 1 ∑ d ∣ gcd ( i , j ) μ ( d ) ∑ p ∈ P min ( ⌊ n p ⌋ , ⌊ m p ⌋ ) ∑ d = 1 μ ( d ) ⋅ ⌊ n p d ⌋ ⋅ ⌊ m p d ⌋ ∑ p ∈ P ∑ i = 1 n ∑ j = 1 m [ gcd ( i , j ) = p ] ∑ p ∈ P ∑ i = 1 ⌊ n p ⌋ ∑ j = 1 ⌊ m p ⌋ [ gcd ( i , j ) = 1 ] ∑ p ∈ P ∑ i = 1 ⌊ n p ⌋ ∑ j = 1 ⌊ m p ⌋ ∑ d ∣ gcd ( i , j ) μ ( d ) ∑ p ∈ P ∑ d = 1 min ( ⌊ n p ⌋ , ⌊ m p ⌋ ) μ ( d ) ⋅ ⌊ n p d ⌋ ⋅ ⌊ m p d ⌋
考虑继续化简,令 T = p d T = p d ,则上式化为:
∑ p ∈ P min ( ⌊ n p ⌋ , ⌊ m p ⌋ ) ∑ d = 1 μ ( d ) ⋅ ⌊ n T ⌋ ⋅ ⌊ m T ⌋ min ( n , m ) ∑ T = 1 ⌊ n T ⌋ ⋅ ⌊ m T ⌋ ⋅ ∑ p | T , p ∈ P μ ( T p ) ∑ p ∈ P ∑ d = 1 min ( ⌊ n p ⌋ , ⌊ m p ⌋ ) μ ( d ) ⋅ ⌊ n T ⌋ ⋅ ⌊ m T ⌋ ∑ T = 1 min ( n , m ) ⌊ n T ⌋ ⋅ ⌊ m T ⌋ ⋅ ∑ p | T , p ∈ P μ ( T p )
记 H ( n ) = ∑ p | n , p ∈ P μ ( n p ) H ( n ) = ∑ p | n , p ∈ P μ ( n p ) ,则原式化为:
min ( n , m ) ∑ T = 1 H ( T ) ⋅ ⌊ n T ⌋ ⋅ ⌊ m T ⌋ ∑ T = 1 min ( n , m ) H ( T ) ⋅ ⌊ n T ⌋ ⋅ ⌊ m T ⌋
考虑预处理出 H ( n ) H ( n ) 。可以使用 " 倍数法 ",对于每个质数 p p ,让其去贡献它的每一个倍数 T T ,稍微卡卡常也可以过。更高明的做法是挖掘 H ( n ) H ( n ) 的一些性质,然后使用线性筛将 H ( n ) H ( n ) 筛出来,这里直接给出结论:
H ( n ) = ⎧ ⎪ ⎨ ⎪ ⎩ 1 n ∈ P − H ( n p ) + μ ( n p ) p ∣ n , p 2 ∤ n μ ( n p ) p ∣ n , p 2 ∣ n H ( n ) = { 1 n ∈ P − H ( n p ) + μ ( n p ) p ∣ n , p 2 ∤ n μ ( n p ) p ∣ n , p 2 ∣ n
预处理出 H ( n ) H ( n ) 后再处理出它的前缀和。这样就可以配合数论分块求出答案的值了。
时间复杂度 O ( n + Q √ n ) O ( n + Q n ) 。
5.1.5:【LOJ #6627】「XXOI 2019」等比数列三角形
LOJ #6627 。
Description
给出一个正整数 n n 。请你求出:有多少个合法的三角形,满足三边都是 ≤ n ≤ n 的整数,且三边成等比数列。
数据范围:1 ≤ n ≤ 10 12 1 ≤ n ≤ 10 12 。
时空限制:1000 m s / 256 M i B 1000 m s / 256 M i B 。
Solution
枚举公差,将公差表示成一个既约分数 k = p q ≥ 1 k = p q ≥ 1 的形式,也就是说我们要保证 gcd ( p , q ) = 1 gcd ( p , q ) = 1 。
对于任意的一个三角形,不妨设三边中的最短边为 x x ,则三边为 x , k x , k 2 x x , k x , k 2 x 。
考虑公差 k = p q k = p q 有一些什么限制:
需要满足三角形的 " 两边之和大于第三边 ",即:
x + k x > k 2 x 1 ≤ k < 1 + √ 5 2 x + k x > k 2 x 1 ≤ k < 1 + 5 2
设 e = 1 + √ 5 2 e = 1 + 5 2 ,根据上面的两条限制,不难得出 q q 关于 p p 的取值范围:
⌈ p e ⌉ ≤ q ≤ p ⌈ p e ⌉ ≤ q ≤ p
p 2 q 2 x ∈ Z q 2 ∣ x p 2 q 2 x ∈ Z q 2 ∣ x
由于 q 2 ∣ x q 2 ∣ x ,可设 i = x q 2 i = x q 2 ,则答案为:
∑ p ∑ ⌈ p e ⌉ ≤ q ≤ p [ gcd ( p , q ) = 1 ] ∑ i = 1 [ p 2 ⋅ i ≤ n ] √ n ∑ p = 1 ⌊ n p 2 ⌋ ⋅ ∑ ⌈ p e ⌉ ≤ q ≤ p [ gcd ( p , q ) = 1 ] ∑ p ∑ ⌈ p e ⌉ ≤ q ≤ p [ gcd ( p , q ) = 1 ] ∑ i = 1 [ p 2 ⋅ i ≤ n ] ∑ p = 1 n ⌊ n p 2 ⌋ ⋅ ∑ ⌈ p e ⌉ ≤ q ≤ p [ gcd ( p , q ) = 1 ]
记 S ( n , p ) = n ∑ i = 1 [ gcd ( i , p ) = 1 ] S ( n , p ) = ∑ i = 1 n [ gcd ( i , p ) = 1 ] ,考虑化简该函数:
S ( n , p ) = n ∑ i = 1 ∑ d ∣ gcd ( i , p ) μ ( d ) = ∑ d ∣ p μ ( d ) ⋅ ⌊ n d ⌋ S ( n , p ) = ∑ i = 1 n ∑ d ∣ gcd ( i , p ) μ ( d ) = ∑ d ∣ p μ ( d ) ⋅ ⌊ n d ⌋
回到问题中,答案化为:
√ n ∑ p = 1 ⌊ n p 2 ⌋ ⋅ [ S ( p , p ) − S ( ⌈ p e ⌉ − 1 , p ) ] ∑ p = 1 n ⌊ n p 2 ⌋ ⋅ [ S ( p , p ) − S ( ⌈ p e ⌉ − 1 , p ) ]
使用 " 倍数法 ",计算出函数 g ( p ) = S ( p , p ) − S ( ⌈ p e ⌉ − 1 , p ) g ( p ) = S ( p , p ) − S ( ⌈ p e ⌉ − 1 , p ) ,然后直接算即可。
时间复杂度 O ( √ n log √ n ) O ( n log n ) 。
6:杜教筛
有时候,我们需要快速地对一些数论函数求前缀和,甚至是需要在低于线性时间 的复杂度内求解。这时可以利用杜教筛来求出这些前缀和。
一般地,给出一个数论函数 f ( x ) f ( x ) ,你需要求出 S ( n ) = n ∑ i = 1 f ( i ) S ( n ) = ∑ i = 1 n f ( i ) 。
注意到,对于任意一个数论函数 g g ,必定会满足:
n ∑ i = 1 ( f ∗ g ) ( i ) = n ∑ i = 1 ∑ d ∣ i g ( d ) ⋅ f ( i d ) = n ∑ i = 1 ⌊ n i ⌋ ∑ j = 1 g ( i ) ⋅ f ( j ) = n ∑ i = 1 g ( i ) ⋅ ⌊ n i ⌋ ∑ j = 1 f ( j ) = n ∑ i = 1 g ( i ) ⋅ S ( ⌊ n i ⌋ ) ∑ i = 1 n ( f ∗ g ) ( i ) = ∑ i = 1 n ∑ d ∣ i g ( d ) ⋅ f ( i d ) = ∑ i = 1 n ∑ j = 1 ⌊ n i ⌋ g ( i ) ⋅ f ( j ) = ∑ i = 1 n g ( i ) ⋅ ∑ j = 1 ⌊ n i ⌋ f ( j ) = ∑ i = 1 n g ( i ) ⋅ S ( ⌊ n i ⌋ )
故有:
g ( 1 ) S ( n ) = n ∑ i = 1 ( f ∗ g ) ( i ) − n ∑ i = 2 g ( i ) ⋅ S ( ⌊ n i ⌋ ) g ( 1 ) S ( n ) = ∑ i = 1 n ( f ∗ g ) ( i ) − ∑ i = 2 n g ( i ) ⋅ S ( ⌊ n i ⌋ )
此时我们得到了一个 S ( n ) S ( n ) 关于 S ( ⌊ n i ⌋ ) S ( ⌊ n i ⌋ ) 的递推式。若 f ∗ g f ∗ g 与 g g 的前缀和都较好处理的话,就可以考虑使用数论分块来处理上面的递推式,较短时间内求出 S ( n ) S ( n ) ,因此找到一个合适的数论函数 g g 是关键。
如果直接使用数论分块做上面的递推式,根据 ⌊ n d ⌋ ⌊ n d ⌋ 的取值进行分段。 不考虑递归的情况下,单纯去处理一个 S ( n ) S ( n ) 的复杂度是 O ( √ n ) O ( n ) 的,递归下去的复杂度为低阶小量 o ( √ n ) o ( n ) ,故计算 S ( n ) S ( n ) 的复杂度为:
O ( √ n ) + √ n ∑ i = 1 O ( √ i ) + √ n ∑ i = 1 O ( √ n i ) O ( n ) + ∑ i = 1 n O ( i ) + ∑ i = 1 n O ( n i )
简单积分近似一下:
√ n ∑ i = 1 O ( √ i ) + √ n ∑ i = 1 O ( √ n i ) ≈ O ⎛ ⎜ ⎝ ∫ n 1 2 0 [ x 1 2 + ( n x ) 1 2 ] dx ⎞ ⎟ ⎠ = O ( n 3 4 ) ∑ i = 1 n O ( i ) + ∑ i = 1 n O ( n i ) ≈ O ( ∫ 0 n 1 2 [ x 1 2 + ( n x ) 1 2 ] dx ) = O ( n 3 4 )
可以积分近似证明,先线性筛预处理出 f ( x ) f ( x ) 的前 n 2 3 n 2 3 项,可以取得杜教筛的理论最优复杂度 O ( n 2 3 ) O ( n 2 3 ) 。
对于一些较大的 n n ,需要使用 std::map
来存下对应的值(记忆化),方便以后使用时直接计算出结果。
6.1:例题选讲
6.1.1:【Luogu P4213】Sum
Luogu P4213 。
Description
给出一个正整数 n n ,请你求出:
a n s 1 = n ∑ i = 1 φ ( i ) a n s 2 = n ∑ i = 1 μ ( i ) a n s 1 = ∑ i = 1 n φ ( i ) a n s 2 = ∑ i = 1 n μ ( i )
数据范围:1 ≤ n < 2 31 1 ≤ n < 2 31 。
时空限制:2000 m s / 512 M i B 2000 m s / 512 M i B 。
Solution
莫比乌斯函数前缀和
注意到 μ ∗ 1 = ϵ μ ∗ 1 = ϵ ,则考虑使用常数函数 1 ( n ) = 1 1 ( n ) = 1 来构造递推式:
S ( n ) = 1 − n ∑ i = 2 S ( ⌊ n i ⌋ ) S ( n ) = 1 − ∑ i = 2 n S ( ⌊ n i ⌋ )
然后直接筛即可。
欧拉函数前缀和
注意到 φ ∗ 1 = ID φ ∗ 1 = ID ,则考虑使用常数函数 1 ( n ) = 1 1 ( n ) = 1 来构造递推式:
S ( n ) = n ( n + 1 ) 2 − n ∑ i = 2 S ( ⌊ n i ⌋ ) S ( n ) = n ( n + 1 ) 2 − ∑ i = 2 n S ( ⌊ n i ⌋ )
然后直接筛即可,但其实更好的做法是莫比乌斯反演。
view code #include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
const int SZ = 1e6 ;
int n;
int m, prime[SZ + 10 ], fac[SZ + 10 ], mu[SZ + 10 ];
int Smu[SZ + 10 ];
void sieve (int N) {
mu[1 ] = 1 ;
for (int i = 2 ; i <= N; i ++) {
if (!fac[i]) fac[i] = i, prime[++ m] = i, mu[i] = -1 ;
for (int j = 1 ; j <= m; j ++) {
if (prime[j] > fac[i] || prime[j] > N / i) break ;
fac[i * prime[j]] = prime[j];
mu[i * prime[j]] = mu[i] * (i % prime[j] ? -1 : 0 );
}
}
for (int i = 1 ; i <= N; i ++)
Smu[i] = Smu[i - 1 ] + mu[i];
}
std ::map <int , int > Smu_buc;
int Smu_calc (int n) {
if (n <= SZ) return Smu[n];
if (Smu_buc.count(n)) return Smu_buc[n];
int cur = 1 ;
for (long long x = 2 , nx; x <= n; x = nx + 1 ) {
nx = n / (n / x);
cur -= (nx - x + 1 ) * Smu_calc(n / x);
}
return Smu_buc[n] = cur;
}
void work () {
scanf ("%d" , &n);
long long ans1 = 0 ;
int ans2 = Smu_calc(n);
for (long long x = 1 , nx; x <= n; x = nx + 1 ) {
nx = n / (n / x);
ans1 += 1ll * (Smu_calc(nx) - Smu_calc(x - 1 )) * (n / x) * (n / x);
}
ans1 = (ans1 + 1 ) / 2 ;
printf ("%lld %d\n" , ans1, ans2);
}
int main () {
sieve(SZ);
int T;
scanf ("%d" , &T);
while (T --) work();
return 0 ;
}
6.1.2:【Luogu P3768】简单的数学题
Luogu P3768 。
Description
给出一个正整数 n n ,请你求出:
n ∑ i = 1 n ∑ j = 1 i ⋅ j ⋅ gcd ( i , j ) ∑ i = 1 n ∑ j = 1 n i ⋅ j ⋅ gcd ( i , j )
答案对给定的质数 p p 取模。
数据范围:1 ≤ n ≤ 10 10 1 ≤ n ≤ 10 10 ,5 × 10 8 ≤ p ≤ 1.1 × 10 9 5 × 10 8 ≤ p ≤ 1.1 × 10 9 。
时空限制:4000 m s / 256 M i B 4000 m s / 256 M i B 。
Solution
利用 φ ∗ 1 = ID φ ∗ 1 = ID 反演,得:
n ∑ i = 1 n ∑ j = 1 i ⋅ j ⋅ ∑ d ∣ gcd ( i , j ) φ ( d ) n ∑ d = 1 φ ( d ) ⋅ ∑ d ∣ i ∑ d ∣ j i ⋅ j n ∑ d = 1 φ ( d ) ⋅ d 2 ⋅ ⌊ n d ⌋ ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 i ⋅ j ∑ i = 1 n ∑ j = 1 n i ⋅ j ⋅ ∑ d ∣ gcd ( i , j ) φ ( d ) ∑ d = 1 n φ ( d ) ⋅ ∑ d ∣ i ∑ d ∣ j i ⋅ j ∑ d = 1 n φ ( d ) ⋅ d 2 ⋅ ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ n d ⌋ i ⋅ j
记 F ( n ) = n ∑ i = 1 i = n ( n + 1 ) 2 F ( n ) = ∑ i = 1 n i = n ( n + 1 ) 2 ,则答案化为:
n ∑ d = 1 φ ( d ) ⋅ d 2 ⋅ F 2 ( ⌊ n d ⌋ ) ∑ d = 1 n φ ( d ) ⋅ d 2 ⋅ F 2 ( ⌊ n d ⌋ )
考虑使用数论分块处理上式,现在的问题是要求出函数 H ( n ) = φ ( n ) ⋅ n 2 H ( n ) = φ ( n ) ⋅ n 2 的前缀和,考虑杜教筛。
线性筛的部分相信大家都会,主要是讨论构造 S ( n ) = n ∑ i = 1 H ( i ) S ( n ) = ∑ i = 1 n H ( i ) 关于 S ( ⌊ n i ⌋ ) S ( ⌊ n i ⌋ ) 递推式的部分。
注意到恒等函数 ID 2 ID 2 ,考虑将 H H 与 ID 2 ID 2 卷在一起:
( H ∗ ID 2 ) ( n ) = ∑ d ∣ n φ ( d ) ⋅ d 2 ⋅ ( n d ) 2 = ∑ d ∣ n φ ( d ) ⋅ n 2 = n 2 ⋅ ∑ d | n φ ( d ) = n 3 ( H ∗ ID 2 ) ( n ) = ∑ d ∣ n φ ( d ) ⋅ d 2 ⋅ ( n d ) 2 = ∑ d ∣ n φ ( d ) ⋅ n 2 = n 2 ⋅ ∑ d | n φ ( d ) = n 3
于是可以得到 H ∗ ID 2 = ID 3 H ∗ ID 2 = ID 3 ,我们发现 ID 2 ID 2 与 ID 3 ID 3 的前缀和都可以直接 Θ ( 1 ) Θ ( 1 ) 计算(实在记不清楚公式的话,直接上拉格朗日插值吧),于是我们就可以得到 S ( n ) S ( n ) 的递推式:
S ( n ) = ( n ( n + 1 ) 2 ) 2 − n ∑ i = 2 i 2 ⋅ S ( ⌊ n i ⌋ ) S ( n ) = ( n ( n + 1 ) 2 ) 2 − ∑ i = 2 n i 2 ⋅ S ( ⌊ n i ⌋ )
直接上数论分块即可。
6.1.3:【BZOJ #4804】欧拉心算(加强版)
Description
给出两个正整数 n , m n , m ,请你求出:
n ∑ i = 1 m ∑ j = 1 φ ( gcd ( i , j ) ) ∑ i = 1 n ∑ j = 1 m φ ( gcd ( i , j ) )
数据范围:1 ≤ n , m ≤ 10 9 1 ≤ n , m ≤ 10 9 。
时空限制:1500 m s / 512 M i B 1500 m s / 512 M i B 。
Solution
n ∑ i = 1 m ∑ j = 1 φ ( gcd ( i , j ) ) = ∑ d = 1 φ ( d ) ⋅ n ∑ i = 1 m ∑ j = 1 [ gcd ( i , j ) = d ] = ∑ d = 1 φ ( d ) ⋅ ⌊ n d ⌋ ∑ i = 1 ⌊ m d ⌋ ∑ j = 1 [ gcd ( i , j ) = 1 ] = ∑ d = 1 φ ( d ) ⋅ ⌊ n d ⌋ ∑ i = 1 ⌊ m d ⌋ ∑ j = 1 ∑ p ∣ gcd ( i , j ) μ ( p ) = ∑ d = 1 φ ( d ) ⋅ ∑ p = 1 μ ( p ) ⋅ ⌊ n p d ⌋ ⋅ ⌊ m p d ⌋ ∑ i = 1 n ∑ j = 1 m φ ( gcd ( i , j ) ) = ∑ d = 1 φ ( d ) ⋅ ∑ i = 1 n ∑ j = 1 m [ gcd ( i , j ) = d ] = ∑ d = 1 φ ( d ) ⋅ ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ [ gcd ( i , j ) = 1 ] = ∑ d = 1 φ ( d ) ⋅ ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ ∑ p ∣ gcd ( i , j ) μ ( p ) = ∑ d = 1 φ ( d ) ⋅ ∑ p = 1 μ ( p ) ⋅ ⌊ n p d ⌋ ⋅ ⌊ m p d ⌋
记 T = p d T = p d ,则式子化简为:
min ( n , m ) ∑ T = 1 ⌊ n T ⌋ ⋅ ⌊ m T ⌋ ⋅ ⎛ ⎝ ∑ d ∣ T φ ( d ) ⋅ μ ( T d ) ⎞ ⎠ ∑ T = 1 min ( n , m ) ⌊ n T ⌋ ⋅ ⌊ m T ⌋ ⋅ ( ∑ d ∣ T φ ( d ) ⋅ μ ( T d ) )
设 g = φ ∗ μ g = φ ∗ μ (这里的 ∗ ∗ 是狄利克雷卷积,下文同),则式子化简为:
min ( n , m ) ∑ T = 1 ⌊ n T ⌋ ⋅ ⌊ m T ⌋ ⋅ g ( T ) ∑ T = 1 min ( n , m ) ⌊ n T ⌋ ⋅ ⌊ m T ⌋ ⋅ g ( T )
可以用数论分块处理上式,现在的问题是要求 g g 的前缀和。可以考虑杜教筛,设:
S ( n ) = n ∑ i = 1 g ( i ) S ( n ) = ∑ i = 1 n g ( i )
记 d = 1 ∗ 1 d = 1 ∗ 1 ,其中函数 1 ( n ) = 1 1 ( n ) = 1 ,显然函数 d d 为约数个数函数。
那么可以得到 S ( n ) S ( n ) 有关 S ( ⌊ n d ⌋ ) S ( ⌊ n d ⌋ ) 的递推式:
d ( 1 ) S ( n ) = n ∑ i = 1 ( g ∗ d ) ( i ) − n ∑ i = 2 d ( i ) ⋅ S ( ⌊ n i ⌋ ) d ( 1 ) S ( n ) = ∑ i = 1 n ( g ∗ d ) ( i ) − ∑ i = 2 n d ( i ) ⋅ S ( ⌊ n i ⌋ )
化简:
d ( 1 ) S ( n ) = n ∑ i = 1 ( ( φ ∗ 1 ) ∗ ( μ ∗ 1 ) ) ( i ) − n ∑ i = 2 d ( i ) ⋅ S ( ⌊ n i ⌋ ) d ( 1 ) S ( n ) = n ( n + 1 ) 2 − n ∑ i = 2 d ( i ) ⋅ S ( ⌊ n i ⌋ ) d ( 1 ) S ( n ) = ∑ i = 1 n ( ( φ ∗ 1 ) ∗ ( μ ∗ 1 ) ) ( i ) − ∑ i = 2 n d ( i ) ⋅ S ( ⌊ n i ⌋ ) d ( 1 ) S ( n ) = n ( n + 1 ) 2 − ∑ i = 2 n d ( i ) ⋅ S ( ⌊ n i ⌋ )
约数个数函数前缀和 h ∑ i = 1 d ( i ) ∑ i = 1 h d ( i ) 即为 h ∑ i = 1 ⌊ h i ⌋ ∑ i = 1 h ⌊ h i ⌋ 。直接用数论分块求解,复杂度较大。运用类似杜教筛的方法处理,具体地:
对于 x ≤ n 2 3 x ≤ n 2 3 的部分:运用线性筛求解每个 S ( x ) , ∑ x i = 1 d ( i ) S ( x ) , ∑ i = 1 x d ( i )
对于 x > n 2 3 x > n 2 3 的部分:运用数论分块求解 ∑ x i = 1 d ( i ) ∑ i = 1 x d ( i ) ,运用递推式求解 S ( x ) S ( x ) 。
可以证明两部分的复杂度均为 O ( n 2 3 ) O ( n 2 3 ) ,直接上数论分块即可。
泛滥河水将我冲向你的心头,不停流 ......
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探