[Algorithm] BAEKJOON 1929 - 소수 구하기 C++(시간 초과 해결)

E0u0n·2024년 3월 21일
0

Algorithm

목록 보기
1/4
post-thumbnail

[BAEKJOON] 1929번 소수 구하기

문제 M이상 N이하의 소수를 모두 출력하는 프로그램을 작성하시오.

입력 첫째 줄에 자연수 M과 N이 빈 칸을 사이에 두고 주어진다. (1 ≤ M ≤ N ≤ 1,000,000) M이상 N이하의 소수가 하나 이상 있는 입력만 주어진다.

출력 한 줄에 하나씩, 증가하는 순서대로 소수를 출력한다.

출처 : [wikipedia] 에라토스테네스의 체

2부터 차례대로 소수를 구하게 되면 시간 초과 결과와 마주하게된다. 이를 해결하기 위해서는 에라토스테네스의 체를 이용해야한다. 에라토스테네스의 체는 특정 범위가 주어졌을 때 그 범위 내의 소수를 찾는 빠르고 쉬운 방법이다.

Input

3 6

Output

3 5 7 11 13

Code

using namespace std;

int main(){
    ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
	
    int min, max;
    cin >> min>>max;


    bool arr[max];
    arr[0] = arr[1] = false;

    for(int i=2; i<=max; i++)
        arr[i] = true;


    for(int i=2; i*i <= max; i++){
        if(!arr[i]) continue;
        for(int j = i*2; j <= max; j += i) arr[j]=false;
    }

    for(int i=min; i<=max; i++)
        if(arr[i]) cout<<i<<'\n';

    return 0;
}

star1

시행착오

처음에는 1434 문제와 비슷한 맥락으로 무작정 소수를 구하는 코드를 작성했다. 그 결과는 어김없이 시간 초과 라는 결과를 마주했다.

1^1첫번째 시도
#include <iostream>
#include <cmath>

using namespace std;

bool isPrime(long long n)
{
    for(int i=2; i<=sqrt(n); i++)
            if(n%i == 0) return false;

    return true;
}

int main(){
    ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
	
    long long min, max;
    cin >> min>>max;

    for(int i=min; i<=max; i++){
        while(isPrime(i)){
            cout << i << endl;
            i++;
        }  
    }

    return 0;
}
2^2두번째 시도

wikipedia에서 제공해주는 C++ 코드 기반으로 소수 구하기 코드를 작성했더니 어김없이 마주친 시간 초과 OTL..

using namespace std;

int main(){
    ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
	
    int min, max;
    cin >> min>>max;

    bool arr[max];
    arr[0] = arr[1] = false;

    for(int i=2; i<=max; i++)
        arr[i] = true;

    for(int i=2; i*i <= max; i++){
        if(!arr[i]) continue;
        for(int j = i*i; j <= max; j += i) arr[j]=false;
    }

    for(int i=min; i<=max; i++) if(arr[i]) cout<<i<<endl;
      
    return 0;
}
3^3세번째 시도

사실 스스로의 힘으로 풀어보고 싶어서 여러번 도전 끝에 10번의 시간 초과 결과를 받고 다른 사람들의 코드를 찾아보기 시작했다. 그러다 ★한 줄기 빛☆ 같은 글을 발견하였다.

5. 에라토스테네스의 체를 구현할 때 흔히 안쪽 루프를 int j = i * i로 시작하는데, 
이렇게 하면 i가 46341이 되는 순간부터 
i * i가 int의 범위를 초과하기 때문에 오버플로우가 발생합니다. 
long long을 사용하거나, i * i 대신 i * 2부터 시작하는 등의 방법을 사용하세요.

이 글을 믿고 i*i 대신 i*2 로 시작하는 코드로 수정했더니 마법처럼 시간 초과의 저주가 풀렸다!

...생략
        
    for(int i=2; i*i <= max; i++){
        if(!arr[i]) continue;
        for(int j = i*2; j <= max; j += i) arr[j]=false;
    }

...

그리고 같은 글에서 앞으로의 코드 스타일에 변화를 주는 문장을 만났다. "추가로 endl은 버퍼를 flush하기 때문에 너무 느립니다. \n을 대신 사용하세요." 지금부터 endl을 내주고 '\n'를 취한다!

profile
이세계 개발자입니다.

0개의 댓글

관련 채용 정보