更好的算法 - 下一个半刚性

9 algorithm optimization primes sieve-of-eratosthenes primality-test

给定n,求m使得m是小于n的最小半素.

下一个素数非常简单,半素质不那么简单.需要说明的是,只需要半刚性,尽管同时获取因子会很方便.

我想到了一些方法,但我确信有更好的方法.

算术运算假定为O(1).我使用了Eratosthenes的Sieve,它是O(n log log n),我知道Atkin的Sieve,但我喜欢我的半优化的Eratosthenes.

从n算起

从n开始计数,当你找到半数时停止.

这看起来真的很愚蠢但如果有一个O(log n)半素测试或O(1)测试给出下面的素数,这可能比其他2更快.

Semiprime分布似乎远高于主要分布,因此通过良好的半素测试,这实际上可能优于O(n).

2.倒计时

定义prev(x)和next(x)并分别给出上一个和下一个素数,如果素数存储在树中或使用列表二进制搜索,则可以是O(log n).

先做筛子.

从p = prev(sqrt(n))开始,q = next(n/p).当pq <= n时,转到下一个q.如果pq小于目前为止的最小值,则将其记录为新的最小值.继续前一个p,直到用完p进行测试.

这可以保证找到正确答案,但速度相当慢.仍然是O(n log n),所以也许可以接受.

3.计票数量增加

像往常一样从筛子开始.为O(1)素性测试创建筛子的哈希集视图.

从p = 2开始.通过素数迭代到sqrt(n).对于每个p,得到q =(((n/p + 1)/ 2)*2)+1 =(((n/p + 1)>> 1)<< 1)| 1.虽然到目前为止pq小于最小值且q不是素数,但是将q加2.如果pq仍小于最小值,则将其记录为新的最小值.


我在Java中实现了#1和#3,两者都使用了相同的Eratosthenes Sieve实现.大部分的运行时间都花在筛选上,所以如果要进行优化,那就是在筛子中.在一些优化之后,向上计数(#1)击败计数(#3),在最后一次和最大测试(11位十进制数n)中快两倍.

但仍然有希望,因为需要延长筛子的距离取决于最大数量的主要测试.如果存在具有较低质数测试界限的半素测试,则计数方法可能更快.

当然有一个更好的算法?或者至少有更好的方法来实现这个?

小智 0

您可以预先计算所有半素数,然后使用二分搜索。100 万以内有 80k 个素数,因此 10^12 以下有 30 亿个半素数。可能不需要太多时间。