P4213 【模板】杜教筛 - 教程
题目描述
给定一个正整数 n n n,求
a n s 1 = ∑ i = 1 n φ ( i ) ans_1=\sum_{i=1}^n\varphi(i) ans1=i=1∑nφ(i)
a n s 2 = ∑ i = 1 n μ ( i ) ans_2=\sum_{i=1}^n \mu(i) ans2=i=1∑nμ(i)
输入格式
本题单测试点内有多组数据。
输入的第一行为一个整数,表示数据组数 T T T。
接下来 T T T 行,每行一个整数 n n n,表示一组询问。
输出格式
对于每组询问,输出一行两个整数,分别代表 a n s 1 ans_1 ans1 和 a n s 2 ans_2 ans2。
输入输出样例 #1
输入 #1
6
1
2
8
13
30
2333
输出 #1
1 1
2 0
22 -2
58 -3
278 -3
1655470 2
说明/提示
数据规模与约定
对于全部的测试点,保证 1 ≤ T ≤ 10 1 \leq T \leq 10 1≤T≤10, 1 ≤ n < 2 31 1 \leq n \lt 2^{31} 1≤n<231。
好!把“杜教筛”(求积性函数的前缀和)的来龙去脉一步讲清楚。核心只有三件事:狄利克雷卷积恒等式、把和式按 (\big\lfloor \frac n i\big\rfloor) 分块、递归+记忆化。
一、目标与思路
我们希望快速计算积性函数的前缀和
S
f
(
n
)
=
∑
i
=
1
n
f
(
i
)
.
S_f(n)=\sum_{i=1}^n f(i).
Sf(n)=i=1∑nf(i).
杜教筛利用两点:
1)狄利克雷卷积恒等式;
2)按 (
⌊
n
i
⌋
\left\lfloor \frac{n}{i}\right\rfloor
⌊in⌋) 分块(整除分块)+ 记忆化递归。
二、狄利克雷卷积与前缀和的关系
卷积定义:
(
f
∗
g
)
(
n
)
=
∑
d
∣
n
f
(
d
)
,
g
(
n
/
d
)
.
(f*g)(n)=\sum_{d\mid n} f(d),g(n/d).
(f∗g)(n)=d∣n∑f(d),g(n/d).
若已知 (f*g=h),对 (k=1,\dots,n) 求和并换序:
∑
k
=
1
n
h
(
k
)
=
∑
k
=
1
n
∑
d
∣
k
f
(
d
)
g
(
k
/
d
)
=
∑
i
=
1
n
f
(
i
)
∑
m
=
1
⌊
n
/
i
⌋
g
(
m
)
=
∑
i
=
1
n
f
(
i
)
,
S
g
!
(
⌊
n
i
⌋
)
.
\sum_{k=1}^n h(k) =\sum_{k=1}^n\sum_{d\mid k} f(d)g(k/d) =\sum_{i=1}^n f(i)\sum_{m=1}^{\lfloor n/i\rfloor} g(m) =\sum_{i=1}^n f(i),S_g!\Big(\Big\lfloor \frac{n}{i}\Big\rfloor\Big).
k=1∑nh(k)=k=1∑nd∣k∑f(d)g(k/d)=i=1∑nf(i)m=1∑⌊n/i⌋g(m)=i=1∑nf(i),Sg!(⌊in⌋).
设
H
(
n
)
=
∑
k
=
1
n
h
(
k
)
,
H(n)=\sum_{k=1}^n h(k),
H(n)=k=1∑nh(k),
则
H
(
n
)
=
∑
i
=
1
n
f
(
i
)
,
S
g
!
(
⌊
n
i
⌋
)
.
H(n)=\sum_{i=1}^n f(i),S_g!\Big(\Big\lfloor \frac{n}{i}\Big\rfloor\Big).
H(n)=i=1∑nf(i),Sg!(⌊in⌋).
当 (
g
(
1
)
≠
0
g(1)\neq 0
g(1)=0) 时,把 (i=1) 项单独拿出可写成
H
(
n
)
=
f
(
1
)
,
S
g
(
n
)
+
∑
i
=
2
n
f
(
i
)
,
S
g
!
(
⌊
n
i
⌋
)
.
H(n)=f(1),S_g(n)+\sum_{i=2}^n f(i),S_g!\Big(\Big\lfloor \frac{n}{i}\Big\rfloor\Big).
H(n)=f(1),Sg(n)+i=2∑nf(i),Sg!(⌊in⌋).
选择合适的 (
g
g
g)(使 (
S
g
S_g
Sg) 易算),再把右侧转化为只含 (
S
f
(
⌊
n
/
i
⌋
)
S_f(\lfloor n/i\rfloor)
Sf(⌊n/i⌋)) 的递推。
三、两个经典目标函数
1. 欧拉函数 ( φ \varphi φ)
恒等式
φ
∗
1
=
i
d
,
i
d
(
n
)
=
n
,
1
(
n
)
≡
1.
\varphi * \mathbf{1} = \mathrm{id},\qquad \mathrm{id}(n)=n,\quad \mathbf{1}(n)\equiv 1.
φ∗1=id,id(n)=n,1(n)≡1.
求和得
∑
k
=
1
n
k
=
∑
i
=
1
n
φ
(
i
)
,
⌊
n
i
⌋
.
\sum_{k=1}^n k=\sum_{i=1}^n \varphi(i),\Big\lfloor \frac{n}{i}\Big\rfloor.
k=1∑nk=i=1∑nφ(i),⌊in⌋.
左边
H
(
n
)
=
n
(
n
+
1
)
2
,
S
1
(
x
)
=
x
.
H(n)=\frac{n(n+1)}{2},\qquad S_{\mathbf{1}}(x)=x.
H(n)=2n(n+1),S1(x)=x.
用整除分块,把 (
⌊
n
/
i
⌋
\lfloor n/i\rfloor
⌊n/i⌋) 相同的 (
i
∈
[
l
,
r
]
i\in[l,r]
i∈[l,r]) 归为一块,块长为 (
(
r
−
l
+
1
)
(r-l+1)
(r−l+1)),块内和为 (
S
φ
(
r
)
−
S
φ
(
l
−
1
)
S_\varphi(r)-S_\varphi(l-1)
Sφ(r)−Sφ(l−1))。整理可得常用递推式
S
φ
(
n
)
=
n
(
n
+
1
)
2
−
∑
l
=
2
n
S
φ
!
(
⌊
n
l
⌋
)
,
(
r
−
l
+
1
)
,
\boxed{S_\varphi(n)=\frac{n(n+1)}{2}-\sum_{l=2}^{n} S_\varphi!\Big(\Big\lfloor\frac{n}{l}\Big\rfloor\Big),(r-l+1),}
Sφ(n)=2n(n+1)−l=2∑nSφ!(⌊ln⌋),(r−l+1),
其中
r
=
⌊
n
⌊
n
/
l
⌋
⌋
.
r=\Big\lfloor \frac{n}{\lfloor n/l\rfloor}\Big\rfloor.
r=⌊⌊n/l⌋n⌋.
初值:( S φ ( 1 ) = 1 S_\varphi(1)=1 Sφ(1)=1)。
2. 莫比乌斯函数 (\mu)
恒等式
μ
∗
1
=
ε
,
ε
(
1
)
=
1
,
ε
(
n
>
1
)
=
0.
\mu * \mathbf{1} = \varepsilon,\qquad \varepsilon(1)=1,\ \varepsilon(n>1)=0.
μ∗1=ε,ε(1)=1,ε(n>1)=0.
求和得
1
=
∑
i
=
1
n
μ
(
i
)
,
⌊
n
i
⌋
.
1=\sum_{i=1}^n \mu(i),\Big\lfloor \frac{n}{i}\Big\rfloor.
1=i=1∑nμ(i),⌊in⌋.
同样整除分块,得到
,
S
μ
(
n
)
=
1
−
∑
l
=
2
n
S
μ
!
(
⌊
n
l
⌋
)
,
(
r
−
l
+
1
)
,
\boxed{,S_\mu(n)=1-\sum_{l=2}^{n} S_\mu!\Big(\Big\lfloor\frac{n}{l}\Big\rfloor\Big),(r-l+1),}
,Sμ(n)=1−l=2∑nSμ!(⌊ln⌋),(r−l+1),
其中 (
r
=
⌊
n
⌊
n
/
l
⌋
⌋
r=\left\lfloor \dfrac{n}{\lfloor n/l\rfloor}\right\rfloor
r=⌊⌊n/l⌋n⌋)。
初值:( S μ ( 1 ) = 1 S_\mu(1)=1 Sμ(1)=1)。
实现注意事项(易错点)
- ( S μ ( n ) ) S_\mu(n)) Sμ(n)) 的初值是 (1),不是 ( n ( n + 1 ) 2 \dfrac{n(n+1)}{2} 2n(n+1))。
- 计算 ( n ( n + 1 ) 2 \dfrac{n(n+1)}{2} 2n(n+1)) 要用更大中间类型避免溢出.
七、两条公式一键记忆
欧拉函数前缀和:
S φ ( n ) = n ( n + 1 ) 2 − ∑ l = 2 n S φ ! ( ⌊ n l ⌋ ) , ( r − l + 1 ) , r = ⌊ n ⌊ n / l ⌋ ⌋ . S_\varphi(n)=\frac{n(n+1)}{2}-\sum_{l=2}^{n} S_\varphi!\Big(\Big\lfloor\frac{n}{l}\Big\rfloor\Big),(r-l+1),\qquad r=\Big\lfloor \frac{n}{\lfloor n/l\rfloor}\Big\rfloor. Sφ(n)=2n(n+1)−l=2∑nSφ!(⌊ln⌋),(r−l+1),r=⌊⌊n/l⌋n⌋.莫比乌斯前缀和:
S μ ( n ) = 1 − ∑ l = 2 n S μ ! ( ⌊ n l ⌋ ) , ( r − l + 1 ) , r = ⌊ n ⌊ n / l ⌋ ⌋ . S_\mu(n)=1-\sum_{l=2}^{n} S_\mu!\Big(\Big\lfloor\frac{n}{l}\Big\rfloor\Big),(r-l+1),\qquad r=\Big\lfloor \frac{n}{\lfloor n/l\rfloor}\Big\rfloor. Sμ(n)=1−l=2∑nSμ!(⌊ln⌋),(r−l+1),r=⌊⌊n/l⌋n⌋.
时间复杂度: O ( n 2 / 3 ) O(n^{2/3}) O(n2/3)
模板
#include
using namespace std;
typedef long long ll;
const int N=2e6+10;
ll n;
ll mu[N];
ll phi[N],pm[N];
unordered_mapmp_phi,mp_mu;
bool vis[N];
int cnt=0;
void init()
{
mu[1]=phi[1]=1;
for(ll i=2;i<=N-10;i++)
{
if(!vis[i])
{
pm[++cnt]=i;
phi[i]=i-1;
mu[i]=-1;
}
for(ll j=1;pm[j]*i<=N-10;j++)
{
ll p = pm[j];
ll m = i*p;
vis[m]=true;
if(i%p==0)
{
phi[i*p]=phi[i]*p;
break;
}
mu[m]=-mu[i];
phi[i*p] = phi[i]*(p-1);
}
}
for(int i=1;i<=N-10;i++)
{
mu[i]+=mu[i-1];
phi[i]+=phi[i-1];
}
}
ll sphi(ll n)
{
if(n<=N-10)return phi[n];
if(mp_phi[n])return mp_phi[n];
ll ans = n*(n+1)/2;
ll r;
for(ll l=2;l<=n;l=r+1)
{
r = n/(n/l);
ans -= sphi(n/l)*(r-l+1);
}
return mp_phi[n]=ans;
}
ll smu(ll n)
{
if(n<=N-10)return mu[n];
if(mp_mu[n])return mp_mu[n];
ll ans = 1;
ll r;
for(ll l=2;l<=n;l=r+1)
{
r = n/(n/l);
ans -= smu(n/l)*(r-l+1);
}
return mp_mu[n]=ans;
}
void solve()
{
cin>>n;
ll ans1 = sphi(n);
ll ans2 = smu(n);
cout<>t;
init();
while(t--)
{
solve();
}
return 0;
}
浙公网安备 33010602011771号