📜  从a到b确实有n个不同的素数

📅  最后修改于: 2021-04-29 11:50:56             🧑  作者: Mango

您将得到两个数字a和b(1 <= a,b <= 10 ^ 8)和n。任务是找到a和b之间的所有数字,包括正好是n个不同的素数。该解决方案的设计方式应像竞争编程中那样有效地处理针对a和b的不同值的多个查询。

例子:

Input  : a = 1, b = 10, n = 2
Output : 2
// Only 6 = 2*3 and 10 = 2*5 have exactly two 
// distinct prime factors

Input : a = 1, b = 100, n = 3
Output: 8
// only 30 = 2*3*5, 42 = 2*3*7, 60 = 2*2*3*5, 66 = 2*3*11,
// 70 = 2*5*7, 78 = 2*3*13, 84 = 2*2*3*7 and 90 = 2*3*3*5 
// have exactly three distinct prime factors

这个问题基本上是分段筛的应用。众所周知,一个数字的所有素数总是小于或等于数字的平方根,即; sqrt(n)。因此,我们生成所有小于或等于10 ^ 8的质数,并将它们存储在数组中。现在,使用此分段筛子,我们检查从a到b的每个数字是否有n个素数。

C++
// C++ program to find numbers with exactly n distinct
// prime factor numbers from a to b
#include
using namespace std;
  
// Stores all primes less than and equals to sqrt(10^8) = 10000
vector  primes;
  
// Generate all prime numbers less than or equals to sqrt(10^8)
// = 10000 using sieve of sundaram
void segmentedSieve()
{
    int n = 10000; // Square root of 10^8
  
    // In general Sieve of Sundaram, produces primes smaller
    // than (2*x + 2) for a number given number x.
    // Since we want primes smaller than n=10^4, we reduce
    // n to half
    int nNew = (n-2)/2;
  
    // This array is used to separate numbers of the form
    // i+j+2ij from others where  1 <= i <= j
    bool marked[nNew + 1];
  
    // Initalize all elements as not marked
    memset(marked, false, sizeof(marked));
  
    // Main logic of Sundaram.  Mark all numbers of the
    // form i + j + 2ij as true where 1 <= i <= j
    for (int i=1; i<=nNew; i++)
        for (int j=i; (i + j + 2*i*j) <= nNew; j++)
            marked[i + j + 2*i*j] = true;
  
    // Since 2 is a prime number
    primes.push_back(2);
  
    // Remaining primes are of the form 2*i + 1 such that
    // marked[i] is false.
    for (int i=1; i<=nNew; i++)
        if (marked[i] == false)
            primes.push_back(2*i+1);
}
  
// Function to count all numbers from a to b having exactly
// n prime factors
int Nfactors(int a, int b, int n)
{
    segmentedSieve();
  
    // result --> all numbers between a and b having
    // exactly n prime factors
    int result = 0;
  
    //  check for each number
    for (int i=a; i<=b; i++)
    {
        // tmp  --> stores square root of current number because
        //          all prime factors are always less than and
        //          equal to square root of given number
        // copy --> it holds the copy of current number
        int tmp = sqrt(i), copy = i;
  
        // count -->  it counts the number of distinct prime
        // factors of number
        int count = 0;
  
        // check divisibility of 'copy' with each prime less
        // than 'tmp' and divide it until it is divisible by
        // current prime factor
        for (int j=0; primes[j]<=tmp; j++)
        {
            if (copy%primes[j]==0)
            {
                // increment count for distinct prime
                count++;
                while (copy%primes[j]==0)
                    copy = copy/primes[j];
            }
        }
  
        // if number is completely divisible then at last
        // 'copy' will be 1 else 'copy' will be prime, so
        // increment count by one
        if (copy != 1)
            count++;
  
        // if number has exactly n distinct primes then
        // increment result by one
        if (count==n)
            result++;
    }
    return result;
}
  
// Driver program to run the case
int main()
{
    int a = 1, b = 100, n = 3;
    cout << Nfactors(a, b, n);
    return 0;
}


Java
// Java program to find numbers with exactly n distinct
// prime factor numbers from a to b
import java.util.*;
  
class GFG
{
      
// Stores all primes less than and 
// equals to sqrt(10^8) = 10000
static ArrayList primes = new ArrayList();
  
// Generate all prime numbers less 
// than or equals to sqrt(10^8)
// = 10000 using sieve of sundaram
static void segmentedSieve()
{
    int n = 10000; // Square root of 10^8
  
    // In general Sieve of Sundaram, 
    // produces primes smaller
    // than (2*x + 2) for a number 
    // given number x. Since we want 
    // primes smaller than n=10^4, 
    // we reduce n to half
    int nNew = (n - 2)/2;
  
    // This array is used to separate 
    // numbers of the form i+j+2ij 
    // from others where 1 <= i <= j
    boolean[] marked=new boolean[nNew + 1];
  
    // Main logic of Sundaram. Mark all 
    // numbers of the form i + j + 2ij
    // as true where 1 <= i <= j
    for (int i = 1; i <= nNew; i++)
        for (int j = i; (i + j + 2 * i * j) <= nNew; j++)
            marked[i + j + 2 * i * j] = true;
  
    // Since 2 is a prime number
    primes.add(2);
  
    // Remaining primes are of the form 2*i + 1 such that
    // marked[i] is false.
    for (int i = 1; i <= nNew; i++)
        if (marked[i] == false)
            primes.add(2 * i + 1);
}
  
// Function to count all numbers from a to b having exactly
// n prime factors
static int Nfactors(int a, int b, int n)
{
    segmentedSieve();
  
    // result --> all numbers between a and b having
    // exactly n prime factors
    int result = 0;
  
    // check for each number
    for (int i = a; i <= b; i++)
    {
        // tmp --> stores square root of current number because
        //     all prime factors are always less than and
        //     equal to square root of given number
        // copy --> it holds the copy of current number
        int tmp = (int)Math.sqrt(i), copy = i;
  
        // count --> it counts the number of distinct prime
        // factors of number
        int count = 0;
  
        // check divisibility of 'copy' with each prime less
        // than 'tmp' and divide it until it is divisible by
        // current prime factor
        for (int j = 0; primes.get(j) <= tmp; j++)
        {
            if (copy % primes.get(j) == 0)
            {
                // increment count for distinct prime
                count++;
                while (copy % primes.get(j) == 0)
                    copy = copy/primes.get(j);
            }
        }
  
        // if number is completely divisible then at last
        // 'copy' will be 1 else 'copy' will be prime, so
        // increment count by one
        if (copy != 1)
            count++;
  
        // if number has exactly n distinct primes then
        // increment result by one
        if (count == n)
            result++;
    }
    return result;
}
  
// Driver code
public static void main (String[] args) 
{
    int a = 1, b = 100, n = 3;
    System.out.println(Nfactors(a, b, n));
}
}
  
// This code is contributed by chandan_jnu


Python3
# Python3 program to find numbers with 
# exactly n distinct prime factor numbers
# from a to b
import math
  
# Stores all primes less than and 
# equals to sqrt(10^8) = 10000
primes = [];
  
# Generate all prime numbers less than 
# or equals to sqrt(10^8) = 10000
# using sieve of sundaram
def segmentedSieve():
  
    n = 10000; # Square root of 10^8
  
    # In general Sieve of Sundaram, produces
    # primes smaller than (2*x + 2) for a 
    # given number x. Since we want primes 
    # smaller than n=10^4, we reduce n to half
    nNew = int((n - 2) / 2);
  
    # This array is used to separate 
    # numbers of the form i+j+2ij
    # from others where 1 <= i <= j
    marked = [False] * (nNew + 1);
  
    # Main logic of Sundaram. Mark all 
    # numbers of the form i + j + 2ij 
    # as true where 1 <= i <= j
    for i in range(1, nNew + 1):
        j = i;
        while ((i + j + 2 * i * j) <= nNew):
            marked[i + j + 2 * i * j] = True;
            j += 1;
  
    # Since 2 is a prime number
    primes.append(2);
  
    # Remaining primes are of the 
    # form 2*i + 1 such that 
    # marked[i] is false.
    for i in range(1, nNew + 1):
        if (marked[i] == False):
            primes.append(2 * i + 1);
  
# Function to count all numbers 
# from a to b having exactly n 
# prime factors
def Nfactors(a, b, n):
  
    segmentedSieve();
  
    # result --> all numbers between 
    # a and b having exactly n prime
    # factors
    result = 0;
  
    # check for each number
    for i in range(a, b + 1):
  
        # tmp --> stores square root of  
        # current number because all prime 
        # factors are always less than and
        # equal to square root of given number
        # copy --> it holds the copy of 
        #           current number
        tmp = math.sqrt(i);
        copy = i;
  
        # count --> it counts the number of 
        # distinct prime factors of number
        count = 0;
  
        # check divisibility of 'copy' with 
        # each prime less than 'tmp' and  
        # divide it until it is divisible
        # by current prime factor
        j = 0;
        while (primes[j] <= tmp):
            if (copy % primes[j] == 0):
                  
                # increment count for
                # distinct prime
                count += 1;
                while (copy % primes[j] == 0):
                    copy = (copy // primes[j]);
            j += 1;
  
        # if number is completely divisible
        # then at last 'copy' will be 1 else 
        # 'copy' will be prime, so increment
        # count by one
        if (copy != 1):
            count += 1;
  
        # if number has exactly n distinct 
        # primes then increment result by one
        if (count == n):
            result += 1;
  
    return result;
  
# Driver Code
a = 1;
b = 100;
n = 3;
print(Nfactors(a, b, n));
  
# This code is contributed
# by chandan_jnu


C#
// C# program to find numbers with exactly n
// distinct prime factor numbers from a to b
using System;
using System.Collections;
  
class GFG
{
      
// Stores all primes less than and 
// equals to sqrt(10^8) = 10000
static ArrayList primes = new ArrayList();
  
// Generate all prime numbers less 
// than or equals to sqrt(10^8)
// = 10000 using sieve of sundaram
static void segmentedSieve()
{
    int n = 10000; // Square root of 10^8
  
    // In general Sieve of Sundaram, produces 
    // primes smaller than (2*x + 2) for a number 
    // given number x. Since we want primes 
    // smaller than n=10^4, we reduce n to half
    int nNew = (n - 2) / 2;
  
    // This array is used to separate 
    // numbers of the form i+j+2ij 
    // from others where 1 <= i <= j
    bool[] marked = new bool[nNew + 1];
  
    // Main logic of Sundaram. Mark all 
    // numbers of the form i + j + 2ij
    // as true where 1 <= i <= j
    for (int i = 1; i <= nNew; i++)
        for (int j = i; 
            (i + j + 2 * i * j) <= nNew; j++)
            marked[i + j + 2 * i * j] = true;
  
    // Since 2 is a prime number
    primes.Add(2);
  
    // Remaining primes are of the form
    // 2*i + 1 such that marked[i] is false.
    for (int i = 1; i <= nNew; i++)
        if (marked[i] == false)
            primes.Add(2 * i + 1);
}
  
// Function to count all numbers from 
// a to b having exactly n prime factors
static int Nfactors(int a, int b, int n)
{
    segmentedSieve();
  
    // result --> all numbers between a and b 
    // having exactly n prime factors
    int result = 0;
  
    // check for each number
    for (int i = a; i <= b; i++)
    {
        // tmp --> stores square root of current
        // number because all prime factors are 
        // always less than and equal to square 
        // root of given number
        // copy --> it holds the copy of current number
        int tmp = (int)Math.Sqrt(i), copy = i;
  
        // count --> it counts the number of 
        // distinct prime factors of number
        int count = 0;
  
        // check divisibility of 'copy' with each 
        // prime less than 'tmp' and divide it until 
        // it is divisible by current prime factor
        for (int j = 0; (int)primes[j] <= tmp; j++)
        {
            if (copy % (int)primes[j] == 0)
            {
                // increment count for distinct prime
                count++;
                while (copy % (int)primes[j] == 0)
                    copy = copy / (int)primes[j];
            }
        }
  
        // if number is completely divisible then 
        // at last 'copy' will be 1 else 'copy' 
        // will be prime, so increment count by one
        if (copy != 1)
            count++;
  
        // if number has exactly n distinct 
        // primes then increment result by one
        if (count == n)
            result++;
    }
    return result;
}
  
// Driver code
public static void Main() 
{
    int a = 1, b = 100, n = 3;
    Console.WriteLine(Nfactors(a, b, n));
}
}
  
// This code is contributed by mits


PHP
 all numbers between a and b 
    // having exactly n prime factors
    $result = 0;
  
    // check for each number
    for ($i = $a; $i <= $b; $i++)
    {
        // tmp --> stores square root of current 
        // number because all prime factors are 
        // always less than and equal to square
        // root of given number
        // copy --> it holds the copy of current number
        $tmp = sqrt($i);
        $copy = $i;
  
        // count --> it counts the number of 
        // distinct prime factors of number
        $count = 0;
  
        // check divisibility of 'copy' with each 
        // prime less than 'tmp' and divide it until 
        // it is divisible by current prime factor
        for ($j = 0; $primes[$j] <= $tmp; $j++)
        {
            if ($copy % $primes[$j] == 0)
            {
                // increment count for distinct prime
                $count++;
                while ($copy % $primes[$j] == 0)
                    $copy = (int)($copy / $primes[$j]);
            }
        }
  
        // if number is completely divisible then 
        // at last 'copy' will be 1 else 'copy' 
        // will be prime, so increment count by one
        if ($copy != 1)
            $count++;
  
        // if number has exactly n distinct primes 
        // then increment result by one
        if ($count == $n)
            $result++;
    }
    return $result;
}
  
// Driver Code
$a = 1;
$b = 100;
$n = 3;
print(Nfactors($a, $b, $n));
  
// This code is contributed by chandan_jnu
?>


输出:

8

如果您有其他方法可以解决此问题,请分享评论。