Min_25 筛的另一种实现
众所周知,\(\text{Min25}\) 筛的复杂度是假的。
众所周知,虽然洲阁筛的复杂度是真的,但是跑的没 \(\text{Min25}\) 筛快,而且非常难写。
众所周知,\(\text{Min25}\) 筛的复杂度假在了第二部分。
于是我们期望能对第二部分改进,以获得一个复杂度正确,而且比洲阁筛好写一点的筛子。
一些定义:
- \(P\):质数集,\(p_k\) 为第 \(k\) 个质数,特别的,规定 \(p_0=1\)
- \(\operatorname{minp}(n)\):\(n\) 的最小质因子在质数集中的排名
- \(\operatorname{maxp}(n)\):\(\leq \sqrt{n}\) 的最大质数在质数集中的排名
- \(f(i)\):我们要求前缀和的函数
- \(N\):最后要求的 \(\sum_{i=1}^{N}f(i)\),与过程中的 \(n\) 区分
- \(n\):过程中的 \(n\),即 \(n\in\{\lfloor\dfrac{N}{1}\rfloor,\lfloor\dfrac{N}{2}\rfloor,\lfloor\dfrac{N}{3}\rfloor,\ldots,\lfloor\dfrac{N}{N}\rfloor\}\),这样的 \(n\) 一共有 \(\sqrt{N}\) 个。
- \(F(n)\):\(f(i)\) 的前缀和,即 \(F(n)=\sum_{i=1}^{n}f(i)\)
- \(F_p(n)\):\(f(i)\) 在质数处的前缀和,即 \(F_p(n)=\sum_{i=1}^{n}[i\in P]f(i)\)
\(\text{Min25}\) 筛的主要思想是将质数处和合数处的值分开来计算,即:
我们称 \(F_p(N)\) 为第一部分,\(\sum_{j=2}^{N}[j\notin P]f(j)\) 为第二部分。
第一部分是相同的,简单复述一下:
首先构造完全积性函数 \(f'(p)=f(p)\)。设 \(g(i,n)=\sum_{j=2}^{n}[j\in P\vee \operatorname{minp}(j)>i]f'(p)\),那么我们就有 \(F_p(n)=g(\operatorname{maxp}(n),n)\)。
考虑递推 \(g(i,n)\),有初值 \(g(0,n)=\sum_{j=2}^{n}f'(j)\),递推式考虑减去最小质因子为 \(i\) 的贡献,由于是完全积性函数,我们无需枚举质因子的指数:
由于对于 \(p_i>\sqrt{n}\) 的没有需要减去的贡献,因此对于每个 \(n\) 只会有 \(\operatorname{maxp}(n)\) 次的转移,所以复杂度为:
重点分析第二部分。
朴素的 \(\text{Min25}\) 筛在这一部分设的是 \(h(i,n)=\sum_{j=2}^{n}[\operatorname{minp}(j)>i]f(j)\),边界为 \(p_i\geq n\) 时 \(h(i,n)=0\),转移为:
这个递推式的复杂度实际上是 \(O(n^{1-\epsilon})\) 的,因此 \(\text{Min25}\) 实际上并不是亚指数筛。
考虑复杂度在哪里出现了退化:我们枚举了 \(p_j\)。
这很不好。
我们尝试用和 \(g(i,n)\) 一样的思路,每次在 \(h(i+1,n)\) 的基础上加上由 \(p_{i+1}\) 产生的贡献,这样我们可以写出递推式:
还可以更优美一些:
这是什么?为什么式子这么熟悉?
这是洲阁筛的第二部分。
在这里精细实现可以做到 \(O(\dfrac{N^{\frac{3}{4}}}{\log N})\),但是我们期望得到一个更好写的做法。
洲阁筛复杂在哪里?需要写一个后缀和。
为什么会有这个后缀和的贡献而不能像 \(g\) 一样没有贡献?因为存在 \(p_{i+1}>\sqrt{n},e=1\) 时从 \(f(p_{i+1})h(i+1,1)\) 的转移,也就是 \(>\sqrt{n}\) 的质数的贡献。
如何去掉这个转移?在状态中去掉关于质数的贡献。
我们设 \(h(i,n)=\sum_{j=2}^{n}[j\notin P\land \operatorname{minp}(j)>i]f(j)\),此时对于 \(i>\sqrt{n}\) 就有 \(g(i,n)=0\),这样的话状态数就缩减到了 \(O(\dfrac{N^{\frac{3}{4}}}{\log N})\)。
考虑转移:
虽然式子看上去变得更复杂了,但是因为状态数降下来,所以转移可以暴力实现,实现难度和 \(\text{Min25}\) 筛的难度差不多。
由于转移看上去不能确定是 \(O(1)\) 的,因此至此还不能确定总时间复杂度。
考虑对于一个 \(n\) 的总转移次数 \(t(n)\),我们枚举 \(e\),求出能转移到 \(n\) 的整数的数量(先不考虑只从质数处转移,最后乘上一个质数密度即可):
(这里的第一个 \(<\) 是渐进意义上的)
因此第二部分总复杂度为:
完结撒花~
PS:关于实际效率
参考在 \(\text{Min25}\) 筛模板题的提交:
假复杂度做法(\(O(N^{1-\epsilon})\),1.75 s)
正确复杂度做法(\(O(\dfrac{N^{\frac{3}{4}}}{\log N})\),3.27 s)
PN 筛(\(O(N^{\frac{2}{3}})\),4.56 s)
从上往下渐进复杂度在变优,实际速度在变慢