前言
设数论函数 g g g的前缀和为 s ( n ) s(n) s(n)。
对于数论函数
f
,
g
f,g
f,g,求其狄利克雷卷积的前缀和:
∑
i
=
1
n
(
f
∗
g
)
(
i
)
\overset{n}{\underset{i=1}\sum}(f*g)(i)
i=1∑n(f∗g)(i)
=
∑
i
=
1
n
∑
d
=
1
n
f
(
d
)
g
(
i
d
)
[
d
∣
i
]
=\overset{n}{\underset{i=1}\sum}\overset{n}{\underset{d=1}\sum}f(d)g(\frac id)[d|i]
=i=1∑nd=1∑nf(d)g(di)[d∣i]
=
∑
d
=
1
n
∑
i
=
1
n
[
d
∣
i
]
f
(
d
)
g
(
i
d
)
=\overset{n}{\underset{d=1}\sum}\overset{n}{\underset{i=1}\sum}[d|i]f(d)g(\frac id)
=d=1∑ni=1∑n[d∣i]f(d)g(di)
=
∑
d
=
1
n
f
(
d
)
∑
i
=
1
⌊
n
d
⌋
g
(
i
)
=\overset{n}{\underset{d=1}\sum}f(d)\overset{\left\lfloor\frac nd\right\rfloor}{\underset{i=1}\sum}g(i)
=d=1∑nf(d)i=1∑⌊dn⌋g(i)
=
∑
d
=
1
n
f
(
d
)
s
(
⌊
n
d
⌋
)
=\overset{n}{\underset{d=1}\sum}f(d)s\left(\left\lfloor\frac nd\right\rfloor\right)
=d=1∑nf(d)s(⌊dn⌋)
=
∑
d
=
1
n
f
(
d
)
s
(
⌊
n
d
⌋
)
=\overset{n}{\underset{d=1}\sum}f(d)s\left(\left\lfloor\frac nd\right\rfloor\right)
=d=1∑nf(d)s(⌊dn⌋)
这也就是说,若数论函数
f
f
f的前缀和为
n
n
n,则有:
∑
i
=
1
n
(
f
∗
g
)
(
i
)
=
∑
i
=
1
n
g
(
i
)
s
(
⌊
n
i
⌋
)
=
g
(
1
)
s
(
n
)
+
∑
i
=
2
n
g
(
i
)
s
(
⌊
n
i
⌋
)
\overset{n}{\underset{i=1}\sum}(f*g)(i)=\overset{n}{\underset{i=1}\sum}g(i)s\left(\left\lfloor\frac ni\right\rfloor\right)=g(1)s(n)+\overset{n}{\underset{i=2}\sum}g(i)s\left(\left\lfloor\frac ni\right\rfloor\right)
i=1∑n(f∗g)(i)=i=1∑ng(i)s(⌊in⌋)=g(1)s(n)+i=2∑ng(i)s(⌊in⌋)
因此:
g
(
1
)
s
(
n
)
=
∑
i
=
1
n
(
f
∗
g
)
(
i
)
−
∑
i
=
2
n
g
(
i
)
s
(
⌊
n
i
⌋
)
g(1)s(n)=\overset{n}{\underset{i=1}\sum}(f*g)(i)-\overset{n}{\underset{i=2}\sum}g(i)s\left(\left\lfloor\frac ni\right\rfloor\right)
g(1)s(n)=i=1∑n(f∗g)(i)−i=2∑ng(i)s(⌊in⌋)
杜教筛
杜教筛用于快速求数论函数前缀和。
对于要求的函数 f f f,定义其前缀和为 s s s,则需要构造辅助函数 g g g,使得其狄利克雷卷积的前缀和与 g g g函数的点值容易求出。
经典的可以用杜教筛的函数有:
欧拉函数
φ
\varphi
φ:
φ
∗
1
=
i
d
\varphi*1=id
φ∗1=id
莫比乌斯函数
μ
\mu
μ:
μ
∗
1
=
ε
\mu*1=\varepsilon
μ∗1=ε
过程借助递归式 g ( 1 ) s ( n ) = ∑ i = 1 n ( f ∗ g ) ( i ) − ∑ i = 2 n g ( i ) s ( ⌊ n i ⌋ ) g(1)s(n)=\overset{n}{\underset{i=1}\sum}(f*g)(i)-\overset{n}{\underset{i=2}\sum}g(i)s\left(\left\lfloor\frac ni\right\rfloor\right) g(1)s(n)=i=1∑n(f∗g)(i)−i=2∑ng(i)s(⌊in⌋)
杜教筛的过程是:
- 欧拉筛计算前 O ( n 2 3 ) O(n^{\frac 23}) O(n32)的 f , s f,s f,s值
- 用哈希表存计算好的 s s s值来剪枝
- 用整除分块递归计算 s ( n ) s(n) s(n)
用主定理分析一波,可以得知,杜教筛的时间复杂度为 O ( n 2 3 ) O\left(n^{\frac 23}\right) O(n32)
具体做法是:
-
筛 φ \varphi φ:
s ( n ) = ∑ i = 1 n ( φ ∗ 1 ) ( i ) − ∑ i = 2 n s ( ⌊ n i ⌋ ) s(n)=\overset{n}{\underset{i=1}\sum}(\varphi*1)(i)-\overset{n}{\underset{i=2}\sum}s\left(\left\lfloor\frac ni\right\rfloor\right) s(n)=i=1∑n(φ∗1)(i)−i=2∑ns(⌊in⌋)
= ∑ i = 1 n i − ∑ i = 2 n s ( ⌊ n i ⌋ ) =\overset{n}{\underset{i=1}\sum} i-\overset{n}{\underset{i=2}\sum}s\left(\left\lfloor\frac ni\right\rfloor\right) =i=1∑ni−i=2∑ns(⌊in⌋)
前面这个…就需要依靠小学奥数了。 -
筛 μ \mu μ:
s ( n ) = ∑ i = 1 n ( μ ∗ 1 ) ( i ) − ∑ i = 2 n s ( ⌊ n i ⌋ ) s(n)=\overset{n}{\underset{i=1}\sum}(\mu*1)(i)-\overset{n}{\underset{i=2}\sum}s\left(\left\lfloor\frac ni\right\rfloor\right) s(n)=i=1∑n(μ∗1)(i)−i=2∑ns(⌊in⌋)
= ∑ i = 1 n [ i = 1 ] − ∑ i = 2 n s ( ⌊ n i ⌋ ) =\overset{n}{\underset{i=1}\sum}[i=1]-\overset{n}{\underset{i=2}\sum}s\left(\left\lfloor\frac ni\right\rfloor\right) =i=1∑n[i=1]−i=2∑ns(⌊in⌋)
#include<iostream>
#include<unordered_map>
#include<vector>
using namespace std;
#define int long long
const int N=2e6;
long long phi[N+5],mu[N+5];
bool vis[N+5];
vector<int> sta;
void Euler() {
mu[1]=1;
phi[1]=1;
for(int i=2;i<=N;i++) {
if(!vis[i])
mu[i]=-1,
phi[i]=i-1,
sta.push_back(i);
for(auto&j:sta) {
int m=i*j;
if(m>N) break;
vis[m]=true;
if(i%j)
mu[m]=-mu[i],
phi[m]=phi[i]*phi[j];
else {
phi[m]=j*phi[i];
break;
}
}
}
for(int i=1;i<=N;i++)
mu[i]+=mu[i-1],
phi[i]+=phi[i-1];
}
unordered_map<int,pair<long long,long long>> H;
pair<long long,long long> sum(int n) {
if(n<=N) return {phi[n],mu[n]};
if(H.count(n)) return H[n];
pair<long long,long long> ans={(long long)n*(n+1)>>1,1},t;
for(long long l=2,r;l<=n;l=r+1)
r=n/(n/l),
t=sum(n/l),
ans.first-=t.first*(r-l+1),
ans.second-=t.second*(r-l+1);
return H[n]=ans;
}
signed main() {
Euler();
// for(int i=1;i<=100;i++)
// cout<<mu[i]<<' ';
int T;
cin>>T;
while(T--) {
int n;
cin>>n;
auto x=sum(n);
cout<<x.first<<' '<<x.second<<endl;
}
}
更进一步
杜教筛还可以预处理出 ϕ ( x ) = φ ( x ) ⋅ I d k ( x ) \phi(x)=\varphi(x)\cdot Id_k(x) ϕ(x)=φ(x)⋅Idk(x)或 ϕ ( x ) = μ ( x ) ⋅ I d k ( x ) \phi(x)=\mu(x)\cdot Id_k(x) ϕ(x)=μ(x)⋅Idk(x)的前缀和。
-
筛 ϕ ( x ) = φ ( x ) ⋅ I d k ( x ) \phi(x)=\varphi(x)\cdot Id_k(x) ϕ(x)=φ(x)⋅Idk(x):
构造辅助函数 g = I d k g=Id_k g=Idk:
s ( n ) = ∑ i = 1 n ( ϕ ∗ I d k ) ( i ) − ∑ i = 2 n I d k ( i ) s ( ⌊ n i ⌋ ) s(n)=\overset{n}{\underset{i=1}\sum}(\phi*Id_k)(i)-\overset{n}{\underset{i=2}\sum}Id_k(i)s\left(\left\lfloor\frac ni\right\rfloor\right) s(n)=i=1∑n(ϕ∗Idk)(i)−i=2∑nIdk(i)s(⌊in⌋)
= ∑ i = 1 n ∑ d ∣ i φ ( d ) d k ( i d ) k − ∑ i = 2 n d k ⋅ s ( ⌊ n i ⌋ ) =\overset{n}{\underset{i=1}\sum}\overset{}{\underset{d|i}\sum}\varphi(d)d^k\left(\frac i d\right)^k-\overset{n}{\underset{i=2}\sum}d^k\cdot s\left(\left\lfloor\frac ni\right\rfloor\right) =i=1∑nd∣i∑φ(d)dk(di)k−i=2∑ndk⋅s(⌊in⌋)
= ∑ i = 1 n i k ∑ d ∣ i φ ( d ) − ∑ i = 2 n d k ⋅ s ( ⌊ n i ⌋ ) =\overset{n}{\underset{i=1}\sum}i^k\overset{}{\underset{d|i}\sum}\varphi(d)-\overset{n}{\underset{i=2}\sum}d^k\cdot s\left(\left\lfloor\frac ni\right\rfloor\right) =i=1∑nikd∣i∑φ(d)−i=2∑ndk⋅s(⌊in⌋)
注意到有 ∑ d ∣ i φ ( d ) = i \overset{}{\underset{d|i}\sum}\varphi(d)=i d∣i∑φ(d)=i:
= ∑ i = 1 n i k + 1 − ∑ i = 2 n d k ⋅ s ( ⌊ n i ⌋ ) =\overset{n}{\underset{i=1}\sum}i^{k+1}-\overset{n}{\underset{i=2}\sum}d^k\cdot s\left(\left\lfloor\frac ni\right\rfloor\right) =i=1∑nik+1−i=2∑ndk⋅s(⌊in⌋)
至于你怎么求出 x x x次方数的前缀和…这个就要找奥数老师了。=w= -
筛 ϕ ( x ) = μ ( x ) ⋅ I d k ( x ) \phi(x)=\mu(x)\cdot Id_k(x) ϕ(x)=μ(x)⋅Idk(x):
构造辅助函数 g = I d k g=Id_k g=Idk:
s ( n ) = ∑ i = 1 n ( ϕ ∗ I d k ) ( i ) − ∑ i = 2 n I d k ( i ) s ( ⌊ n i ⌋ ) s(n)=\overset{n}{\underset{i=1}\sum}(\phi*Id_k)(i)-\overset{n}{\underset{i=2}\sum}Id_k(i)s\left(\left\lfloor\frac ni\right\rfloor\right) s(n)=i=1∑n(ϕ∗Idk)(i)−i=2∑nIdk(i)s(⌊in⌋)
= ∑ i = 1 n ∑ d ∣ i μ ( d ) d k ( i d ) k − ∑ i = 2 n d k ⋅ s ( ⌊ n i ⌋ ) =\overset{n}{\underset{i=1}\sum}\overset{}{\underset{d|i}\sum}\mu(d)d^k\left(\frac i d\right)^k-\overset{n}{\underset{i=2}\sum}d^k\cdot s\left(\left\lfloor\frac ni\right\rfloor\right) =i=1∑nd∣i∑μ(d)dk(di)k−i=2∑ndk⋅s(⌊in⌋)
= ∑ i = 1 n i k ∑ d ∣ i μ ( d ) − ∑ i = 2 n d k ⋅ s ( ⌊ n i ⌋ ) =\overset{n}{\underset{i=1}\sum}i^k\overset{}{\underset{d|i}\sum}\mu(d)-\overset{n}{\underset{i=2}\sum}d^k\cdot s\left(\left\lfloor\frac ni\right\rfloor\right) =i=1∑nikd∣i∑μ(d)−i=2∑ndk⋅s(⌊in⌋)
注意到有 ∑ d ∣ i μ ( d ) = [ i = 1 ] \overset{}{\underset{d|i}\sum}\mu(d)=[i=1] d∣i∑μ(d)=[i=1]:
= ∑ i = 1 n i k [ i = 1 ] − ∑ i = 2 n d k ⋅ s ( ⌊ n i ⌋ ) =\overset{n}{\underset{i=1}\sum}i^{k}[i=1]-\overset{n}{\underset{i=2}\sum}d^k\cdot s\left(\left\lfloor\frac ni\right\rfloor\right) =i=1∑nik[i=1]−i=2∑ndk⋅s(⌊in⌋)
= 1 − ∑ i = 2 n d k ⋅ s ( ⌊ n i ⌋ ) =1-\overset{n}{\underset{i=2}\sum}d^k\cdot s\left(\left\lfloor\frac ni\right\rfloor\right) =1−i=2∑ndk⋅s(⌊in⌋)
后记
于是皆大欢喜。