Учитывая, что входных данных может быть до 1000000000, как я могу написать более эффективную программу по времени и памяти? (выведите все простые числа между m и n)

Вот код ниже (ответ на CP qs)

Ограничение по времени для выполнения составляет 6 секунд, но мой код медленнее, чем.

Как я могу сделать его более эффективным с точки зрения памяти и времени?

  • Ввод: ввод начинается с количества t тестов в одной строке (t ‹= ​​10).

  • В каждой из следующих t строк находятся по два числа m и n (1 ‹= m ‹= n ‹= 1000000000< /strong>, нм ‹= 100000), разделенных пробелом.

  • Выходные данные: для каждого теста выведите все простые числа p такие, что m ‹= p ‹= n, по одному числу в строке, тесты разделены пустой строкой.

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    long int t,m,n,i,j,k;
    //printf("Enter number of testcases:\n");
    scanf("%ld",&t);
    long int test[t][2];
    for(i=0;i<t;i++){
        //printf("Enter m,n:\n");
        scanf("%ld %ld",&test[i][0],&test[i][1]);
    }
    
    for(k=0;k<t;k++){    
        for(i=test[k][0];i<=test[k][1];i++){
            for(j=2;j*j<i*i;j++){
                if(i%j==0)
                    break;
            }
            if(j==i){
                printf("%ld\n",i);
                }
            }
            printf("\n");
    }
    return 0;
}

person curious_coder17    schedule 20.06.2020    source источник
comment
j раз j ‹ i раз i - что это должно делать?   -  person gnasher729    schedule 20.06.2020
comment
Единственное четное простое число — 2. Кроме того, вы можете игнорировать четные числа. Следовательно, вам не нужно проверять четные делители, j › 2. Проверяйте отдельно 2, а затем начинайте цикл j с 3 и шага 2.   -  person rossum    schedule 20.06.2020
comment
относительно: ` for(i=0;i‹t;i++){ //printf(Введите m,n:\n); scanf(%ld %ld,&test[i][0],&test[i][1]); }` Программа должна знать только о двух значениях после чтения t. Следовательно, нет необходимости сохранять все эти значения, предложите простой цикл, уменьшающий t до 0, а тело цикла должно работать только с двумя последними значениями, считанными из ввода. Кроме того, функции: scanf() и printf() ОЧЕНЬ интенсивно используют ЦП. Предлагайте использовать: getchar_unlocked() и putchar_unlocked()   -  person user3629249    schedule 21.06.2020
comment
доступ к двумерному массиву test[][] снова и снова и снова `- это пустая трата времени. Предлагайте работать только с двумя входными данными одного тестового примера одновременно.   -  person user3629249    schedule 21.06.2020
comment
значение: 1000000000 находится в пределах unsigned int, поэтому не рекомендуется использовать long int   -  person user3629249    schedule 21.06.2020
comment
в вашем описании проблемы про минимизацию потребляемой памяти ничего нет. Поэтому предложите написать отдельную программу для вычисления всех простых чисел от 2 до 10^9 и вставить результаты в вашу «тестовую» программу как static const данные. Тогда решение проблемы простое: прокручивайте простые данные до тех пор, пока не будет найдено значение, равное начальному значению, затем выведите каждое найденное значение, пока (но не включая) значение не превысит конечное значение.   -  person user3629249    schedule 21.06.2020
comment
ОТ Включение файлов заголовков, содержимое которых не используется, является очень плохой практикой программирования. Ничто в опубликованном коде не использует содержимое заголовочного файла: stdlib.h Предлагаю удалить заголовочный файл   -  person user3629249    schedule 21.06.2020
comment
относительно: `for(j=2;jj‹ii;j++){` Это МНОГО умножения, которое не нужно. Предложите включить math.h и вычислить sqrt(i) в отдельную переменную, а затем использовать эту отдельную переменную подобно: int sqrt_n = sqrt( n ); for( j=3; j<=sqrt_n; j+=2 )   -  person user3629249    schedule 21.06.2020
comment
Примечание: время выполнения и использование памяти (почти) всегда являются компромиссом.   -  person user3629249    schedule 21.06.2020
comment
@user3629249 user3629249 в вашем описании проблемы нет ничего о минимизации потребляемой памяти. это в заголовке, а также в теле: как я могу сделать его более эффективным с точки зрения памяти и времени?   -  person Will Ness    schedule 21.06.2020
comment
В комментариях я дал несколько идей по ускорению кода, потому что время выполнения ограничено. и, как я уже говорил, время выполнения и использование памяти являются компромиссом,   -  person user3629249    schedule 21.06.2020
comment
Какой тип процессора вам дали, чтобы попросить быть под 6s? срок должен быть занят архитектурой.   -  person Luis Colorado    schedule 28.06.2020


Ответы (1)


Используйте офсетное сито Эратосфена (см. также этот ответ с псевдокодом; обе ссылки относятся к ответам SO от меня).

Согласно вашим данным, это сегментированное сито Эратосфена, модифицированное для работы только с одним сегментом.

Разница в том, что сегментированное сито работает с сегментами бесконечно и использует столько простых чисел, сколько необходимо просеиваемому в данный момент сегменту (вплоть до квадратного корня его верхнего предела); здесь предел верхнего сегмента (и, следовательно, базового сегмента) известен заранее.

Основной сегмент простирается до sqrt наибольшего рассматриваемого значения; здесь он дан вам как 10^9. sqrt(10^9) < 32000, поэтому основной сегмент охватывает диапазон от 0 до 32000 и просеивается простым ситом Эратосфена.

Поскольку у вас несколько прогонов, используйте одно и то же ядро ​​для каждого прогона.

Код в связанном ответе легко изменить в соответствии с требованиями этого вопроса: вместо оценки значения top просто используйте n, предоставленный вам во входных данных. above здесь называется m.

person Will Ness    schedule 20.06.2020
comment
в связанном коде относительно: // 1000 +: 9 13 19 21 31 33 39 49 51 61 9, 21, 33, 49 не являются простыми Итак, если это пример вывода кода, то код неверен. - person user3629249; 21.06.2020
comment
@user3629249 user3629249 вы неправильно интерпретируете вывод. показанные числа являются дельтами выше предела (здесь 1000). на это намекает +. таким образом, простые числа равны 1009, 1013, 1019, 1021, .... это сделано для более плотного вывода, особенно. с очень большими лимитами. - person Will Ness; 21.06.2020