Exactamente n números primos distintos de a a b

Te dan dos números a y b (1 <= a,b <= 10^8) y n. La tarea es encontrar todos los números entre ayb inclusive que tengan exactamente n factores primos distintos. La solución debe diseñarse de manera que maneje de manera eficiente múltiples consultas para diferentes valores de a y b como en la Programación Competitiva.
Ejemplos: 
 

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

Este problema es básicamente la aplicación del tamiz segmentado . Como sabemos que todos los factores primos de un número son siempre menores o iguales a la raíz cuadrada del número, es decir; sqrt(n). Entonces generamos todos los números primos menores o iguales a 10 ^ 8 y los almacenamos en una array. Ahora, usando este tamiz segmentado, verificamos que cada número de a a b tenga exactamente n factores primos. 
 

C++

// C++ program to find numbers with exactly n distinct
// prime factor numbers from a to b
#include<bits/stdc++.h>
using namespace std;
 
// Stores all primes less than and equals to sqrt(10^8) = 10000
vector <int> 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];
 
    // Initialize 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<Integer> primes = new ArrayList<Integer>();
 
// 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

<?php
// PHP program to find numbers with exactly n
// distinct prime factor numbers from a to b
 
// Stores all primes less than and equals
// to sqrt(10^8) = 10000
$primes = array();
 
// Generate all prime numbers less than or
// equals to sqrt(10^8) = 10000 using
// sieve of sundaram
function segmentedSieve()
{
    global $primes;
    $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 = array_fill(0, $nNew + 1, false);
 
    // Main logic of Sundaram. Mark all numbers of the
    // form i + j + 2ij as true where 1 <= i <= j
    for ($i = 1; $i <= $nNew; $i++)
        for ($j = $i;
            ($i + $j + 2 * $i * $j) <= $nNew; $j++)
            $marked[$i + $j + 2 * $i * $j] = true;
 
    // Since 2 is a prime number
    array_push($primes, 2);
 
    // Remaining primes are of the form 2*i + 1
    // such that marked[i] is false.
    for ($i = 1; $i <= $nNew; $i++)
        if ($marked[$i] == false)
            array_push($primes, 2 * $i + 1);
}
 
// Function to count all numbers from a to b
// having exactly n prime factors
function Nfactors($a, $b, $n)
{
    global $primes;
    segmentedSieve();
 
    // result --> 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
?>

Javascript

<script>
 
    // JavaScript program to find numbers with exactly n
    // distinct prime factor numbers from a to b
     
    // Stores all primes less than and
    // equals to sqrt(10^8) = 10000
    let primes = [];
 
    // Generate all prime numbers less
    // than or equals to sqrt(10^8)
    // = 10000 using sieve of sundaram
    function segmentedSieve()
    {
        let 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
        let nNew = parseInt((n - 2) / 2, 10);
 
        // This array is used to separate
        // numbers of the form i+j+2ij
        // from others where 1 <= i <= j
        let marked = new Array(nNew + 1);
        marked.fill(false);
 
        // Main logic of Sundaram. Mark all
        // numbers of the form i + j + 2ij
        // as true where 1 <= i <= j
        for (let i = 1; i <= nNew; i++)
            for (let j = i;
                (i + j + 2 * i * j) <= nNew; j++)
                marked[i + j + 2 * i * j] = true;
 
        // Since 2 is a prime number
        primes.push(2);
 
        // Remaining primes are of the form
        // 2*i + 1 such that marked[i] is false.
        for (let i = 1; i <= nNew; i++)
            if (marked[i] == false)
                primes.push(2 * i + 1);
    }
 
    // Function to count all numbers from
    // a to b having exactly n prime factors
    function Nfactors(a, b, n)
    {
        segmentedSieve();
 
        // result --> all numbers between a and b
        // having exactly n prime factors
        let result = 0;
 
        // check for each number
        for (let 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
            let tmp = parseInt(Math.sqrt(i), 10), copy = i;
 
            // count --> it counts the number of
            // distinct prime factors of number
            let count = 0;
 
            // check divisibility of 'copy' with each
            // prime less than 'tmp' and divide it until
            // it is divisible by current prime factor
            for (let j = 0; primes[j] <= tmp; j++)
            {
                if (copy % primes[j] == 0)
                {
                    // increment count for distinct prime
                    count++;
                    while (copy % primes[j] == 0)
                        copy = parseInt(copy / primes[j], 10);
                }
            }
 
            // 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;
    }
     
    let a = 1, b = 100, n = 3;
    document.write(Nfactors(a, b, n));
     
</script>

Producción:  

8

Si tiene otro enfoque para resolver este problema, compártalo en los comentarios.
Este artículo es una contribución de Shashank Mishra (Gullu) . Si te gusta GeeksforGeeks y te gustaría contribuir, también puedes escribir un artículo usando write.geeksforgeeks.org o enviar tu artículo por correo a review-team@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.
Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.
 

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *