概述
Min_25是日本一个ACM选手的ID,这个筛法是他发明的,所以称之为Min_25筛。它能在亚线性复杂度求出一类积性函数的
f
f
f 的前缀和,前提 是这个积性函数在质数和质数的幂位置的函数值比较好求。借助埃拉托色尼筛的思想 将原问题转化成与质因子相似的子问题,从而得到一个递推式,达到快速求解的效果。
对比其他算法
(绿色为
O
(
n
)
O(n)
O(n),红色为Min_25筛,蓝色为杜教筛)
可以发现,Min_25时间复杂度尽管只快了杜教筛常数级,但终究是快的
因为Min_25筛不像杜教筛那样需要构造,所以Min_25筛的适用范围更加的广泛。
算法原理
为了方便描述,我们定义一些符号。
-
设我们的问题是 F ( n ) = ∑ i = 1 n f ( i ) F(n)=\sum\limits_{i=1}^{n}f(i) F(n)=i=1∑nf(i) ;假定 f f f 是一个完全积性函数。
-
设 m i n p ( i ) minp(i) minp(i) 表示 i i i 的最小质因子。
-
设 p r k pr_k prk 表示第 k k k 个质数。
-
设 ∣ p r ( n ) ∣ |pr(n)| ∣pr(n)∣ 表示 n n n 以内的质数个数。
-
设 g ( n , i ) g(n,i) g(n,i) 表示在埃拉托色尼筛中,前 i i i 个筛完后,剩下的数的 f f f 值之和。即质数和最小质因子大于 p r i pr_i pri 的合数。
则有
g
(
n
,
i
)
=
∑
(
j
∈
P
r
i
m
e
)
∨
(
m
i
n
p
(
j
)
>
p
r
i
)
f
(
j
)
g(n,i)=\sum\limits_{(j\in Prime)\lor(minp(j)>pr_i)}f(j)
g(n,i)=(j∈Prime)∨(minp(j)>pri)∑f(j)
于是可知
g
(
n
,
∣
p
r
(
n
)
∣
)
g(n,|pr(n)|)
g(n,∣pr(n)∣) 表示的是做完埃氏筛之后,
n
n
n 以内所有质数
f
f
f 值之和,
g
(
p
r
k
,
k
)
g(pr_k,k)
g(prk,k) 表示的是 前
k
k
k 个质数的
f
f
f 值之和(含义差不多)
发现可以用如下的递推式求出
g
(
n
,
i
)
g(n,i)
g(n,i) 的值。
g
(
n
,
i
)
=
{
g
(
n
,
i
−
1
)
,
p
r
i
2
>
n
g
(
n
,
i
−
1
)
−
f
(
p
r
i
)
×
(
g
(
⌊
n
p
r
i
⌋
,
i
−
1
)
−
g
(
p
r
i
−
1
,
i
−
1
)
)
p
r
i
2
≤
n
g(n,i)=\begin{cases}g(n,i-1),& pr_i^2> n\\g(n,i-1)-f(pr_i)\times(g(\lfloor\dfrac{n}{pr_i}\rfloor,i-1)-g(pr_{i-1},i-1))&pr_i^2\le n\end{cases}
g(n,i)=⎩
⎨
⎧g(n,i−1),g(n,i−1)−f(pri)×(g(⌊prin⌋,i−1)−g(pri−1,i−1))pri2>npri2≤n
第一行的式子很容易理解,回忆埃氏筛的方法, n n n 第一次一定是被最小质因子筛掉。 p r i 2 > n pr_i^2>n pri2>n,那么 p r i pr_i pri 不会筛掉任何数,便不会产生任何贡献。
但是第二个式子就比较难理解了,我也花了十几分钟的时间才彻底明白。
首先,
g
(
n
,
i
)
g(n,i)
g(n,i) 较
g
(
n
,
i
−
1
)
g(n,i-1)
g(n,i−1) 而言,就是以
p
r
i
pr_i
pri 为最小质因子的数被筛掉了,那么减去的就应该是
n
n
n 以内以
p
r
i
pr_i
pri 为最小质因子的数。
g
(
⌊
n
p
r
i
⌋
,
i
−
1
)
g(\lfloor\dfrac{n}{pr_i}\rfloor,i-1)
g(⌊prin⌋,i−1) ,除去了一个
p
r
i
pr_i
pri ,得到的
⌊
n
p
r
i
⌋
\lfloor\dfrac{n}{pr_i}\rfloor
⌊prin⌋ 是
n
n
n 以内以
p
r
i
pr_i
pri 为质因子能筛掉的数中,可能出现的除
p
r
i
pr_i
pri 以外倍数的最大值。
所以
g
(
⌊
n
p
r
i
⌋
,
i
−
1
)
g(\lfloor\dfrac{n}{pr_i}\rfloor,i-1)
g(⌊prin⌋,i−1) 得到的是
⌊
n
p
r
i
⌋
\lfloor\dfrac{n}{pr_i}\rfloor
⌊prin⌋ 以内
m
i
n
p
(
x
)
≥
p
r
i
−
1
minp(x)\ge pr_{i-1}
minp(x)≥pri−1 的
f
f
f 值和
∑
j
∈
P
r
i
m
e
p
r
i
−
1
f
(
j
)
\sum\limits_{j\in Prime}^{pr_{i-1}}f(j)
j∈Prime∑pri−1f(j) 之和。
但是埃氏筛时只有满足 m i n p ( x ) ≥ p r i − 1 minp(x)\ge pr_{i-1} minp(x)≥pri−1 的才会被筛掉啊,所以得把 ∑ j ∈ P r i m e p r i − 1 f ( j ) \sum\limits_{j\in Prime}^{pr_{i-1}}f(j) j∈Prime∑pri−1f(j) 给加回来, ∑ j ∈ P r i m e p r i − 1 f ( j ) \sum\limits_{j\in Prime}^{pr_{i-1}}f(j) j∈Prime∑pri−1f(j) 即为 g ( p r i − 1 , i − 1 ) g(pr_{i-1},i-1) g(pri−1,i−1)。
这样它们再乘一个
p
r
i
pr_i
pri ,则得到
n
n
n 以内的最小质因子等于
p
r
i
pr_i
pri 的合数的
f
f
f 值。注意这里,要求
f
f
f 是一个完全积性函数,才能把
f
(
p
r
i
)
f(pr_i)
f(pri) 提取出来。但是
f
f
f 不一定是一个积性函数啊?带着疑问继续往下看。
注意这个递推式,它的初始条件是什么呢?是
g
[
n
]
[
0
]
g[n][0]
g[n][0] ,而
g
[
n
]
[
0
]
g[n][0]
g[n][0] 的意义正是还没有开始进行埃氏筛时的
f
f
f 值之和。这个值是我们需要去求的,怎么可能拿来做初始值呢?
其实这里的 g [ n ] [ 0 ] g[n][0] g[n][0] 里,并不是真正的 f f f 值之和,假设它为 f ′ f' f′ 。在质数和质数的幂的位置, f ′ = f f'=f f′=f;而其他位置不一定, f ′ f' f′ 出现的目的,只是因为这里需要一个完全积性函数,而原来的 f f f 虽然是一个积性函数,但不是完全积性函数。于是用 f ′ f' f′ 去代替 f f f。这样,前面的递推式就成立了。
有时候题目中的
f
f
f 是多项式,我们可以将它拆开,这样每一项都是一个幂的形式,而幂是完全积性函数。这样对每一项通过
g
g
g 的递推式去求,求出后再求和即可。
怎么实现呢?
注意到第二维是可以滚动的,所以空间上可以省掉第二维;有因为
⌊
⌊
n
a
⌋
b
⌋
=
⌊
n
a
b
⌋
\left\lfloor\dfrac{\lfloor\frac{n}{a}\rfloor}{b}\right\rfloor=\lfloor\dfrac{n}{ab}\rfloor
⌊b⌊an⌋⌋=⌊abn⌋,这说明递归下去求的所有
g
g
g 值,都在数论分块的
2
n
2\sqrt{n}
2n 个值中。所以我们一开始就把
2
n
2\sqrt{n}
2n 个值先存下来,然后在上面进行滚动。
现在进入正题,上面的都是预处理。
设
S
(
n
,
i
)
S(n,i)
S(n,i) 表示
n
n
n 以内的最小质因子大于
p
r
i
pr_i
pri 的数的
f
f
f 值之和。
则有
S
(
n
,
i
)
=
g
(
n
,
∣
P
∣
)
−
g
(
p
r
i
,
∣
P
∣
)
+
∑
j
>
i
∑
p
r
j
k
≤
n
f
(
p
r
j
k
)
×
(
S
(
⌊
n
p
r
j
k
⌋
,
j
+
[
k
>
1
]
)
S(n,i)=g(n,|P|)-g(pr_i,|P|)+\sum\limits_{j>i}\sum\limits_{pr_j^k\le n}f(pr_j^k)\times(S(\lfloor\frac{n}{pr_j^k}\rfloor,j+[k>1])
S(n,i)=g(n,∣P∣)−g(pri,∣P∣)+j>i∑prjk≤n∑f(prjk)×(S(⌊prjkn⌋,j+[k>1])
这里有同学提出过问题,为什么不能把
g
(
n
,
∣
P
∣
)
−
g
(
p
r
i
,
∣
P
∣
)
g(n,|P|)-g(pr_i,|P|)
g(n,∣P∣)−g(pri,∣P∣) 去掉,将
[
k
>
1
]
[k>1]
[k>1] 改成
[
k
≥
1
]
[k\ge1]
[k≥1] 呢?
可以是可以的,但是就必须要把
n
n
n 以内所有的质数都枚举出来
那 O(n) 的时间复杂度和直接暴力求前缀和有什么区别?
我们最终要求的值为 S ( n , 0 ) + f ( 1 ) S(n,0) + f(1) S(n,0)+f(1)。(加上 f ( 1 ) f(1) f(1) 是因为1没有质因子,不会被 S ( n , 0 ) S(n,0) S(n,0) 所包括)。
观察上述的递推式,其中的两项已经求出来了,最后的那一项有两个求和号,分别枚举质因子以及质因子的次数,注意此处根据“递归下去求的所有
g
g
g 值,都在数论分块的
2
n
2\sqrt{n}
2n 个值中”,要求的质因子为
n
\sqrt n
n 以内的质因子,所以枚举的总次数大约是:
n
ln
n
×
ln
n
\sqrt{\dfrac{n}{\ln n}}\times\ln n
lnnn×lnn,而
S
(
⌊
n
p
r
j
k
⌋
)
S(\lfloor\dfrac{n}{pr_j^k}\rfloor)
S(⌊prjkn⌋)中的参数,也是在
n
n
n 的数论分块的
O
(
n
)
O(\sqrt n)
O(n) 个值以内。
分析时间复杂度
设
T
(
n
)
T(n)
T(n) 表示上述递推式的时间复杂度,则有:
T
(
n
)
=
O
(
n
ln
n
×
ln
n
)
+
∑
p
r
j
k
T
(
⌊
n
p
r
j
k
⌋
)
T(n)=O(\sqrt{\dfrac{n}{\ln n}}\times\ln n)+\sum\limits_{pr_j^k}T(\lfloor\dfrac{n}{pr_j^k}\rfloor)
T(n)=O(lnnn×lnn)+prjk∑T(⌊prjkn⌋)
= O ( n ln n × ln n ) + 1 ln n ∑ i = 2 n T ( ⌊ n i ⌋ ) =O(\sqrt{\dfrac{n}{\ln n}}\times\ln n)+\dfrac{1}{\ln n}\sum\limits_{i=2}^{n}T(\lfloor\dfrac{n}{i}\rfloor) =O(lnnn×lnn)+lnn1i=2∑nT(⌊in⌋)
= O ( n ln n × ln n ) + 1 ln n ∑ i = 2 n O ( n i ln ( n i ) × ln ( n i ) ) =O(\sqrt{\dfrac{n}{\ln n}}\times\ln n)+\dfrac{1}{\ln n}\sum\limits_{i=2}^{n}O(\sqrt\dfrac{\frac{n}{i}}{\ln(\frac{n}{i})}\times\ln(\frac{n}{i})) =O(lnnn×lnn)+lnn1i=2∑nO(ln(in)in×ln(in))
= O ( n ln n × ln n ) + 1 ln n ∑ i = 2 n O ( i ln ( i ) × ln ( i ) + n i ln ( n i ) × ln ( n i ) =O(\sqrt{\dfrac{n}{\ln n}}\times\ln n)+\dfrac{1}{\ln n}\sum\limits_{i=2}^{\sqrt n}O(\sqrt\dfrac{i}{\ln(i)}\times\ln(i)+\sqrt\dfrac{\frac{n}{i}}{\ln(\frac{n}{i})}\times\ln(\frac{n}{i}) =O(lnnn×lnn)+lnn1i=2∑nO(ln(i)i×ln(i)+ln(in)in×ln(in)
≥ O ( n ln n × ln n ) + 1 ln n ∑ i = 2 n O ( n ln n 4 ) \ge O(\sqrt{\dfrac{n}{\ln n}}\times\ln n)+\dfrac{1}{\ln n}\sum\limits_{i=2}^{\sqrt n}O(\sqrt[4]{n\ln \sqrt n}) ≥O(lnnn×lnn)+lnn1i=2∑nO(4nlnn)
= O ( n ln n × ln n ) + O ( n 3 4 ln n × ln n 4 ) =O(\sqrt{\dfrac{n}{\ln n}}\times\ln n)+O(\dfrac{n^{\frac{3}{4}}}{\ln n}\times\sqrt[4]{\ln \sqrt{n}}) =O(lnnn×lnn)+O(lnnn43×4lnn)
= O ( n 3 4 ln n ) =O(\dfrac{n^\frac{3}{4}}{\ln n}) =O(lnnn43)