Является ли число кубом простого числа C++

Вот код,должен вывести Yes если N-куб простого числа

#include <iostream>
#include <cmath>
using namespace std;

int main() {
    int N;
    cin>>N;
    int k=0;
    for (int i=2;i<N/3+1;i++)
     for (int x=1;x<i;x++){
         if (i%x==0) k+=1;
         if (k == 2 and i*i*i==N) cout<<"Yes"<<endl;
         else cout<<"No"<<endl;}

    return 0;
}

Ответы (2 шт):

Автор решения: Nowhere Man

Cледовало импортировать <iostream>, чтобы пользоваться стандарными потоками ввода-вывода.

Вложенный цикл для определения, является ли число простым, можно переписать, отбрасывая числа кратные 2 и 3, и проверяя числа по формуле 6m ± 1, как показано здесь

#include <cmath>
#include <iostream>
using namespace std;

int main() {
    int N;
    cin >> N;
    int k = 0;
    bool f = false;
    for (int i = 1; !f && i * i * i <= N; i++) {
        bool prime = i > 1 && (i % 2 != 0 || i == 2) && (i % 3 != 0 || i == 3);
        int x = 5;
        int d = 2;
        while (prime && x * x <= i) {
            prime = i % x != 0;
            x += d;
            d = 6 - d;
        }
        f = prime && i * i * i == N;
    }
    if (f) cout << "Yes" << endl;
    else cout << "No" << endl;

    return 0;
}

Тогда для входных значений 1, 64, 216 и т.п. будет выводиться No, так как найденные кубические корни не являются простыми числами.


Возможен и такой оптимизированный вариант с одним циклом, в котором будет досрочный выход, как только потенциальный корень окажется составным числом, и поэтому в цикле будет строгое условие:

bool isPrimeCube(int n) {
    bool prime = n > 1;
    int d = 1;
    int root;
    for (root = 2; prime && root * root * root < n; root += d) {
        prime = n % root != 0;
        switch (root) {
            case 2: d = 1; break;
            case 3: case 5: d = 2; break;
            default: d = 6 - d;
        }
    }
    return prime && root * root * root == n;
}

Тест:

int main() {
    int arr[] = {1, 2, 3, 4, 5, 0, 20, 27, 64, 125, 216, 512, 1000, 1331, 12167};
    for (int N : arr) {
       cout << N << " ? " << (isPrimeCube(N) ? "Yes" : "No") << endl;
    }

    return 0;
}

Результат:

1 ? No
2 ? No
3 ? No
4 ? No
5 ? No
0 ? No
20 ? No
27 ? Yes
64 ? No
125 ? Yes
216 ? No
512 ? No
1000 ? No
1331 ? Yes
12167 ? Yes
→ Ссылка
Автор решения: Stanislav Volodarskiy

icbrt (integer cubic root) находит наибольшее целое, куб которого меньше или равен x. Простой перебор без оптимизаций:

int icbrt(int x) {
    int y = 0;
    // условие цикла равносильно i * i * i <= x но не вызывает
    // переполнение для x близких к верхней границе типа.
    for (int i = 1; i * i <= x / i; ++i) {
        y = i;
    }
    return y;
}

is_prime проверяет что число n простое. То есть больше единицы и не делится на числа в диапазоне [2, n). Простой перебор без оптимизаций:

bool is_prime(int n) {
    if (n <= 1) {
        return false;
    }
    for (int i = 2; i < n; ++i) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

is_cube_of_prime решает задачу - проверяет что n - куб простого числа. Извлекаем кубический корень, проверяем что его куб равен n и что он простой:

bool is_cube_of_prime(int n) {
    int m = icbrt(n);
    return m * m * m == n && is_prime(m);
}

Ввод и вывод:

int main() {
    int n;
    if (std::cin >> n) {
        std::cout << (is_cube_of_prime(n) ? "Yes" : "No") << '\n';
    }
}

P.S. Ничего не оптимизировано, потому что int обычно 32 бита. Максимальное значение куба 1290. Не долго сделать столько итераций чтобы извлечь корень и проверить его на простоту.

→ Ссылка