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

时间:2013-11-04 12:55:05

标签: c++ primes sieve-of-eratosthenes

这里x,y <= 10 ^ 12且y-x <= 10 ^ 6

我从左到右循环并检查每个数字是否为素数。当x和y有点像10 ^ 11和10 ^ 12时,这种方法非常慢。更快的方法? 我将所有素数存储到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;
}

4 个答案:

答案 0 :(得分:10)

使用分段的Eratosthenes筛。

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

y最多10 12 你必须筛选最多10 6 的素数,这将需要不到一秒的时间实施

答案 1 :(得分:1)

This resource在增加复杂性/效率方面经历了许多主要搜索算法。这里是最好的描述,即PG7.8(你必须转换回C ++,它不应该太难)

  

该算法通过从考虑中消除多个先前识别的素数来有效地选择潜在素数   最小化必须执行以验证的测试数量   每个潜在素数的首要地位。而选择的效率   潜在的素数允许程序筛选更大范围的   每秒数字,程序运行的时间越长,测试次数   需要对每个潜在的素数进行的操作继续进行   上升,(但与其他算法相比,上升速度较慢)。   这些过程共同为生成素数带来了更高的效率   数字,甚至生成10位数的经过验证的素数   可以在PC上合理的时间内完成。

     

可以开发进一步的跳过集以消除可能由已经存在的每个素数计算的潜在素数的选择   已经确定。虽然这个过程比较复杂,但也可以   一般化,有点优雅。与此同时,我们可以   继续从每个素数的测试素数集中消除   跳过设置消除倍数,最小化数量   必须对每个潜在素数进行的测试。

答案 2 :(得分:0)

您可以使用Sieve of Eratosthenes算法。此页面包含一些指向各种语言的实现的链接:https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes

答案 3 :(得分:0)

以下是我对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筛来计算阶乘。这实际上是我可以设法创建当天的Sieve的最快解释(它可以在不到一秒的时间内计算出此范围的筛选)