#c
#c
Вопрос:
В чем проблема с этим кодом? Это генератор n-го простого числа. Это дает мне правильный ответ, но выдает ошибку во время выполнения во втором тестовом примере в Timus online judge. Кто-нибудь может мне помочь? Вот мой код.
#include <iostream>
#include <cmath>
using namespace std;
#define MAX 16000
bool prime[MAX];
void sieve() {
prime[0]=prime[1]=true;
int r=sqrt(MAX);
for(int i = 3; i <= r; i ) {
for(int j = i*i; j <= MAX; j =(2*i)) {
prime[j]=true;
}
}
}
int main()
{
int t, n;
sieve();
cin >> t;
for(int i = 0; i < t; i ) {
cin >> n;
int c = 1, k, tk=2;
for(k = 3; c < n; k =2) {
if(k%2!=0 amp;amp; prime[k]==false) {
c ;
tk = k;
}
}
cout << tk << endl;
}
return 0;
}
Комментарии:
1.
for(int j = i*i; j <= MAX; j =(2*i)) { prime[j]=true;
— Что произойдет, еслиj == MAX
? Это одна из причин, по которой нельзя научиться писать безопасный код на C на сайтах онлайн-соревнований. Использованиеstd::vector
иvector::at()
выявило бы эту проблему.2. Каково точное написание вопроса? В частности, максимальные значения
n
,t
?3. @Damien, максимальные значения n, t равны 15000.
4. Если максимальное значение
n
равно 15000, то максимальное простое число будет намного выше 160005. О, я допускаю эту ошибку. Спасибо
Ответ №1:
Одна из вопиющих ошибок заключается в следующем:
#define MAX 16000
bool prime[MAX];
// ...
for(int j = i*i; j <= MAX; j =(2*i)) {
prime[j]=true; // <-- Buffer overrun when j == MAX
Когда j == MAX
вы пишете в prime[MAX]
, когда самый высокий индекс MAX - 1
. Это переполнение буфера, что приводит к неопределенному поведению.
Любой цикл, имеющий <=
в качестве условия продолжение, считается подозрительным. Это ошибочное использование <=
условия in a for
loop является одним из контрольных признаков того, что может произойти поочередный доступ.
Условие, вероятно, должно быть:
for(int j = i*i; j < MAX; j =(2*i)) {
prime[j]=true;
Что касается более безопасного кодирования, которое дает вам C , используя std::array<bool, MAX>
, а затем at()
функция будет отмечать это:
#include <array>
#define MAX 16000
std::array<bool, MAX> prime;
// ...
for(int j = i*i; j <= MAX; j =(2*i)) {
prime.at(j) = true; // <-- std::out_of_range exception thrown
Это std::out_of_range
сразу же вызвало бы исключение j == MAX
, остановив дальнейшую работу вашей программы с (надеюсь) описанием того, почему было вызвано исключение.