📜  数数到 N 正好有 5 个除数

📅  最后修改于: 2022-05-13 01:56:06.914000             🧑  作者: Mango

数数到 N 正好有 5 个除数

给定一个正整数N ,任务是计算范围[1, N]中恰好有 5 个除数的整数个数。

例子:

朴素方法:解决给定问题的最简单方法是迭代范围[1, N]并计算该范围内除数为5的整数。
时间复杂度: O(N 4/3 )
辅助空间: O(1)

有效的方法:上述方法也可以通过观察一个事实来优化,即恰好有5 个除数的数字可以用p 4的形式表示,其中p是素数,因为除数的数量正好是5 。请按照以下步骤解决问题:

  • 通过使用埃拉托色尼筛法生成所有素数,使其四次方小于10 18并将其存储在向量中,例如A[]
  • 初始化两个变量,比如0A.size() – 1
  • 为了执行二分搜索迭代直到小于并执行以下步骤:
    • 找到mid的值作为(low + high)/2
    • 在索引mid (mid – 1)处找到元素的四次方值,并将其存储在变量中,分别表示当前上一个
    • 如果current的值为N ,则打印A[mid]的值作为结果。
    • 如果current的值大于N并且previous最多为 N ,则打印A[mid]的值作为结果。
    • 如果current的值大于N ,则将high的值更新为(mid – 1) 。否则,将low的值更新为(mid + 1)

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
#define ll long long int
const int MAX = 1e5;
using namespace std;
 
// Function to calculate the value of
// (x^y) using binary exponentiation
ll power(ll x, unsigned ll y)
{
    // Stores the value of x^y
    ll res = 1;
 
    // Base Case
    if (x == 0)
        return 0;
 
    while (y > 0) {
 
        // If y is odd multiply
        // x with result
        if (y & 1)
            res = (res * x);
 
        // Otherwise, divide y by 2
        y = y >> 1;
 
        x = (x * x);
    }
    return res;
}
 
// Function to perform the Sieve Of
// Eratosthenes to find the prime
// number over the range [1, 10^5]
void SieveOfEratosthenes(
    vector >& v)
{
    bool prime[MAX + 1];
 
    memset(prime, true, sizeof(prime));
 
    prime[1] = false;
 
    for (int p = 2; p * p <= MAX; p++) {
 
        // If prime[p] is not changed
        // then it is a prime
        if (prime[p] == true) {
 
            // Set all the multiples of
            // p to non-prime
            for (int i = p * 2;
                 i <= MAX; i += p)
                prime[i] = false;
        }
    }
 
    int num = 1;
 
    // Iterate over the range [1, MAX]
    for (int i = 1; i <= MAX; i++) {
 
        // Store all the prime number
        if (prime[i]) {
            v.push_back({ i, num });
            num++;
        }
    }
}
 
// Function to find the primes having
// only 5 divisors
int countIntegers(ll n)
{
    // Base Case
    if (n < 16) {
        return 0;
    }
 
    // First value of the pair has the
    // prime number and the second value
    // has the count of primes till that
    // prime numbers
    vector > v;
 
    // Precomputing all the primes
    SieveOfEratosthenes(v);
 
    int low = 0;
    int high = v.size() - 1;
 
    // Perform the Binary search
    while (low <= high) {
 
        int mid = (low + high) / 2;
 
        // Calculate the fourth power of
        // the curr and prev
        ll curr = power(v[mid].first, 4);
        ll prev = power(v[mid - 1].first, 4);
 
        if (curr == n) {
 
            // Return value of mid
            return v[mid].second;
        }
 
        else if (curr > n and prev <= n) {
 
            // Return value of mid-1
            return v[mid - 1].second;
        }
        else if (curr > n) {
 
            // Update the value of high
            high = mid - 1;
        }
 
        else {
 
            // Update the value of low
            low = mid + 1;
        }
    }
    return 0;
}
 
// Driver Code
int main()
{
    ll N = 100;
    cout << countIntegers(N);
 
    return 0;
}


Java
// Java program for the above approach
import java.util.Vector;
 
public class GFG {
    static int MAX = (int)1e5;
 
    public static class pair {
        long first;
        long second;
        pair(long first, long second)
        {
            this.first = first;
            this.second = second;
        }
    }
    // Function to calculate the value of
    // (x^y) using binary exponentiation
    static long power(long x, long y)
    {
       
        // Stores the value of x^y
        long res = 1;
 
        // Base Case
        if (x == 0)
            return 0;
 
        while (y > 0)
        {
 
            // If y is odd multiply
            // x with result
            if ((y & 1) == 1)
                res = (res * x);
 
            // Otherwise, divide y by 2
            y = y >> 1;
 
            x = (x * x);
        }
        return res;
    }
 
    // Function to perform the Sieve Of
    // Eratosthenes to find the prime
    // number over the range [1, 10^5]
    static void SieveOfEratosthenes(Vector v)
    {
        boolean prime[] = new boolean[MAX + 1];
 
        for (int i = 0; i < prime.length; i++) {
            prime[i] = true;
        }
 
        prime[1] = false;
 
        for (int p = 2; p * p <= MAX; p++) {
 
            // If prime[p] is not changed
            // then it is a prime
            if (prime[p] == true) {
 
                // Set all the multiples of
                // p to non-prime
                for (int i = p * 2; i <= MAX; i += p)
                    prime[i] = false;
            }
        }
 
        int num = 1;
 
        // Iterate over the range [1, MAX]
        for (int i = 1; i <= MAX; i++) {
 
            // Store all the prime number
            if (prime[i]) {
                v.add(new pair(i, num));
                num++;
            }
        }
    }
 
    // Function to find the primes having
    // only 5 divisors
    static long countIntegers(long n)
    {
        // Base Case
        if (n < 16) {
            return 0;
        }
 
        // First value of the pair has the
        // prime number and the second value
        // has the count of primes till that
        // prime numbers
        Vector v = new Vector<>();
 
        // Precomputing all the primes
        SieveOfEratosthenes(v);
 
        int low = 0;
        int high = v.size() - 1;
 
        // Perform the Binary search
        while (low <= high) {
 
            int mid = (low + high) / 2;
 
            // Calculate the fourth power of
            // the curr and prev
            long curr = power(v.get(mid).first, 4);
            long prev = power(v.get(mid - 1).first, 4);
 
            if (curr == n) {
 
                // Return value of mid
                return v.get(mid).second;
            }
 
            else if (curr > n && prev <= n) {
 
                // Return value of mid-1
                return v.get(mid - 1).second;
            }
            else if (curr > n) {
 
                // Update the value of high
                high = mid - 1;
            }
 
            else {
 
                // Update the value of low
                low = mid + 1;
            }
        }
        return 0;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        long N = 100;
        System.out.println(countIntegers(N));
    }
}
 
// This code is contributed by abhinavjain194


输出:
2

时间复杂度: O(N*log N)
辅助空间: O(N)