查找两个大数 x 和 y 之间的素数数的最快方法

fastest method for finding number of prime numbers between two large numbers x and y

本文关键字:之间 数数 方法 两个 查找      更新时间:2023-10-16

here x,y<=10^12 and y-x<=10^6

我从左到右循环并检查每个数字的素数。当 x 和 y 有点像 10^11 和 10^12 时,这种方法非常慢。我 hv 将所有素数存储到 10^6..我可以使用它们来查找 10^10-10^12 等巨大值之间的素数吗?

for(i=x;i<=y;i++)
{
    num=i;
    if(check(num))
    {
        res++;
    }
}

我的支票功能

int check(long long int num)
{
    long long int i;
    if(num<=1)
        return 0;
    if(num==2)
        return 1;
    if(num%2==0)
        return 0;
    long long int sRoot = sqrt(num*1.0);
    for(i=3; i<=sRoot; i+=2)
    {
        if(num%i==0)
            return 0;
    }
    return 1;
}

使用埃拉托色尼的分段筛。

也就是说,使用位集来存储 xy 之间的数字,用 x 表示为偏移量,位设置为 [0,y-x)。然后对所有小于或等于y平方 根的素数进行筛分(消除倍数)。那些留在集合中的数字是质数。

对于最多 1012y,您必须用最多 106 个素数进行筛分,这在正确的实现中将花费不到一秒钟的时间。

该资源通过许多主要搜索算法来提高复杂性/效率。这是最好的描述,即PG7.8(您必须翻译回C++,应该不会太难)

该算法通过从考虑中消除先前识别的素数的倍数来有效地选择潜在的素数,并且 最大限度地减少为验证 每个潜在素数的首要地位。同时选择效率 潜在的素数允许程序筛选更大范围的 每秒数 程序运行的时间越长,测试次数就越多 需要在每个潜在素数上执行的确实继续 上升,(但与其他算法相比,上升速度较慢)。 总之,这些过程为产生素数带来了更高的效率 数字,甚至生成 10 位验证素数 可以在PC上的合理时间内完成。

可以

开发进一步的跳过集,以消除潜在素数的选择,这些素数可以由已经具有的每个素数分解 已被识别。虽然这个过程更复杂,但它可以是 概括并变得有些优雅。同时,我们可以 继续从测试素数集中消除每个素数 跳过集消除了倍数,最大限度地减少了 必须在每个潜在素数上执行的测试。

您可以使用埃拉托色尼筛子算法。此页面包含一些指向各种语言的实现的链接:https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes。

这是我对 Sieve of Erathostenes 的实现:

#include <string>
#include <iostream>
using namespace std;
const int k = 110000; //you can change this constant to whatever maximum int you would need to calculate
long int p[k]; //here we would store Sieve of Erathostenes from 2 to k
long int j; 
void init_prime() //in here we set our array
{
    for (int i = 2; i <= k; i++)
    {
        if (p[i] == 0)
        {
            j = i;
            while (j <= k)
            {
                p[j] = i;
                j = j + i;
            }
        }
    }
    /*for (int i = 2; i <= k; i++)
        cout << p[i] << endl;*/ //if you uncomment this you can see the output of initialization...
}
string prime(int first, int last) //this is example of how you can use initialized array
{
    string result = "";
    for (int i = first; i <= last; i++)
    {
        if (p[i] == i)
            result = result + to_str(i) + "";
    }
    return result;
}
int main() //I done this code some time ago for one contest, when first input was number of cases and then actual input came in so nocases means "number of cases"...
{
    int nocases, first, last;
    init_prime(); 
    cin >> nocases;
    for (int i = 1; i <= nocases; i++)
    {
        cin >> first >> last;
        cout << prime(first, last);
    }
    return 0;
}

您也可以使用Erathostenes筛来计算阶乘。这实际上是我当天可以设法创建的筛子的最快解释(它可以在不到一秒钟的时间内计算出这个范围的筛子)