📜  生成从1到Nth的质数的新算法

📅  最后修改于: 2021-04-24 15:18:13             🧑  作者: Mango

除了使用Eratosthenes的Sieve方法生成素数外,我们还可以实现一种新算法来生成从1N的素数。

知道可以从一个模式中跟踪所有≥5的质数可能令人惊讶:
让我们尝试理解该系列:

我们看到将6加到5并再次将6加到获得的结果中,我们可以获得另一个素数。类似地,将6加到7,然后再次将6加到获得的结果中。我们可以得到另一个素数。因此,我们可以推断出我们可以通过相同的过程获得所有素数。
但是,当我们继续将6与上一个结果相加以获得下一个质数时,我们会注意到一些不是质数的数。
例如:

我们可以将这些类型的复合数称为伪素数(作为素数出现,但实际上不是)。
现在,如果我们能够将这些伪素数与真实素数分开,我们就可以获得真实素数。使用4个重要方程,我们可以精确地跟踪所有这些伪素数并将它们与实素数分开。

将产生级数的方程为:

我们可以使用4个方程式跟踪所有伪素数:

对于从y = 6 * x – 1产生的级数:

  1. y =(6 * d * x)+ d其中,x = {1,2,3,4,5,6,…}
  2. y =(6 * d * x)+(d * d)其中,x = {0,1,2,3,4,5,…}和d = {5,(5 + 6),(5 + 6) +6),(5 + 6 + 6 + 6),…,(5+(n-1)* 6)}

对于从y = 6 * x + 1产生的级数:

  1. y =(6 * d * x)+(d * d)其中,x = {0,1,2,3,…}
  2. y =(6 * d * x)+(d * d)– 2 * d其中,x = {1,2,3,4,…},d = {7,(7 + 6),(7 + 6) +6),…,(7 +(n – 1)* 6)}和n = {1、2、3、4、5,…}

如何在编程中实现?

下面是该方法的实现:

// C++ implementation of the approach
#include 
using namespace std;
  
// Function to return the count of prime numbers <= n
int countPrimesUpto(int n)
{
  
    // To store the count of prime numbers
    int count = 0;
  
    // To mark all the prime numbers according
    // to the equation (y = 6*x -/+ 1)
    // where x = 1, 2, 3, 4, 5, 6, 7, ...
    bool arr1[n + 1];
  
    // To mark all the Pseudo Prime Numbers
    // using the four equations
    // described in the approach
    bool arr2[n + 1];
  
    // Starting with >= 5
    int d = 5;
  
    // 2 and 3 are primes
    arr1[2] = arr2[2] = 1;
    arr1[3] = arr2[3] = 1;
  
    // Initialize every element of arr1 with 0
    memset(arr1, 0, sizeof(arr1));
  
    // Initialize every element of arr2 with 1
    memset(arr2, 1, sizeof(arr2));
  
    // Update arr1[] to mark all the primes
    while (d <= n) {
  
        // For 5, (5 + 6), (5 + 6 + 6), ...
        memset(arr1 + d, 1, (sizeof(arr1)) / (n + 1));
  
        // For 7, (7 + 6), (7 + 6 + 6), ...
        memset(arr1 + (d + 2), 1, (sizeof(arr1)) / (n + 1));
  
        // Increase d by 6
        d = d + 6;
    }
  
    // Update arr2[] to mark all pseudo primes
    for (int i = 5; i * i <= n; i = i + 6) {
        int j = 0;
  
        // We will run while loop until we find all
        // pseudo prime numbers <= n
        while (1) {
            int flag = 0;
  
            // Equation 1
            int temp1 = 6 * i * (j + 1) + i;
  
            // Equation 2
            int temp2 = ((6 * i * j) + i * i);
  
            // Equation 3
            int temp3 = ((6 * (i + 2) * j)
                         + ((i + 2) * (i + 2)));
  
            // Equation 4
            int temp4 = ((6 * (i + 2) * (j + 1))
                         + ((i + 2) * (i + 2)) - 2 * (i + 2));
  
            // If obtained pseudo prime number <=n then its
            // corresponding index in arr2 is set to 0
  
            // Result of equation 1
            if (temp1 <= n) {
                arr2[temp1] = 0;
            }
            else {
                flag++;
            }
  
            // Result of equation 2
            if (temp2 <= n) {
                arr2[temp2] = 0;
            }
            else {
                flag++;
            }
  
            // Result of equation 3
            if (temp3 <= n) {
                arr2[temp3] = 0;
            }
            else {
                flag++;
            }
  
            // Result of equation 4
            if (temp4 <= n) {
                arr2[temp4] = 0;
            }
            else {
                flag++;
            }
  
            if (flag == 4) {
                break;
            }
            j++;
        }
    }
  
    // Include 2
    if (n >= 2)
        count++;
  
    // Include 3
    if (n >= 3)
        count++;
  
    // If arr1[i] = 1 && arr2[i] = 1 then i is prime number
    // i.e. it is a prime which is not a pseudo prime
    for (int p = 5; p <= n; p = p + 6) {
        if (arr2[p] == 1 && arr1[p] == 1)
            count++;
  
        if (arr2[p + 2] == 1 && arr1[p + 2] == 1)
            count++;
    }
  
    return count;
}
  
// Driver code
int main()
{
    int n = 100;
    cout << countPrimesUpto(n);
}
输出:
25