PS/BaekJoon

[BaekJoon 4948번] 베르트랑 공준(C++)

박땅콩 2022. 12. 5.
728x90

※주의※

저의 풀이가 정답은 아닙니다.

다른 코드가 더 효율적이거나 좋을 수 있습니다.

언제나 다른 사람의 코드는 참고만 하시기 바랍니다.

 

 

[문제 풀이 사이트]

 

 

 

4948번: 베르트랑 공준

베르트랑 공준은 임의의 자연수 n에 대하여, n보다 크고, 2n보다 작거나 같은 소수는 적어도 하나 존재한다는 내용을 담고 있다. 이 명제는 조제프 베르트랑이 1845년에 추측했고, 파프누티 체비쇼

www.acmicpc.net

 

 

[문제 설명]

 

 

베르트랑 공준은 임의의 자연수 n에 대하여, n보다 크고, 2n보다 작거나 같은 소수는 적어도 하나 존재한다는 내용을 담고 있다.

이 명제는 조제프 베르트랑이 1845년에 추측했고, 파프누티 체비쇼프가 1850년에 증명했다.

예를 들어, 10보다 크고, 20보다 작거나 같은 소수는 4개가 있다. (11, 13, 17, 19) 또, 14보다 크고, 28보다 작거나 같은 소수는 3개가 있다. (17,19, 23)

자연수 n이 주어졌을 때, n보다 크고, 2n보다 작거나 같은 소수의 개수를 구하는 프로그램을 작성하시오. 

 

 

[입력]

 

 

입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 케이스는 n을 포함하는 한 줄로 이루어져 있다.

입력의 마지막에는 0이 주어진다.

 

 

[출력]

 

 

각 테스트 케이스에 대해서, n보다 크고, 2n보다 작거나 같은 소수의 개수를 출력한다.

 

 

[제한사항]

 

 

  • 1 ≤ n ≤ 123,456

 

 

[입출력 예]

 

 

입력 출력

10 
13 
100 
1000 
10000 
100000 
0



21 
135 
1033 
8392

 

 

[문제 풀이]

 

 

자연수 n이 주어졌을 때 n보다 크고, 2n보다 작거나 같은 소수의 개수를 구해야 한다.

그리고 입력이 여러개 이므로, 매 입력이 들어올 때마다 소수의 개수를 구하기엔 시간이 많이 소요된다.

그래서 처음에 n의 최대 범위인 123456에서 2를 곱한 범위까지 소수를 구하도록 하여 입력 여러번이 들어와도 매번 소수를 구하지 않도록 했다.

 

소수를 구하는 방법은 에라토스테네스의 체를 사용했다.

(아래 포스트를 참조바란다.)

 

[Algorithm] 에라토스테네스의 체

위 짤은 인터넷을 돌아다니다가 재밌어서 가져와봤습니다. 무튼 글을 시작하자면 알고리즘 문제를 풀다보면 소수 판별하라는 문제가 종종 보입니다. 해당 문제를 해결하기 위해선 소수 판별하

park-peanut.tistory.com

 

이전에 알고리즘 정리한 내용과 관련된 문제를 풀면서 내용을 상기시키는 것이 좋다.

기억력 벽이 더욱 더 단단해지는 것 같다. 

 

[최종 코드]

 

 

[GitHub]

 

 

 

GitHub - SmallPeanutPark/BAEKJOON: Study BaekJoon for Coding Test

Study BaekJoon for Coding Test. Contribute to SmallPeanutPark/BAEKJOON development by creating an account on GitHub.

github.com

 

 

#include <bits/stdc++.h>

using namespace std;

vector<bool> ischecked;

int main(void) {
    unsigned long long n;
    unsigned long long num = 123456 * 2;
    ischecked.resize(num + 1);
    fill(ischecked.begin(), ischecked.end(), true);

    for(unsigned long long i = 2; i <= num; ++i) {
        if(!ischecked[i]) continue;
            for(unsigned long long j = i * i; j <= num; j += i) {
                ischecked[j] = false; // 소수가 아님
        }
    }

    while(cin >> n) {
        if(n == 0) break;
        unsigned long long n2 = 2 * n;
        unsigned long long ans = 0;

        for(unsigned long long i = n + 1; i <= n2; ++i) {
            if(ischecked[i]) {
                ans += 1;
            }
        }
        cout << ans << '\n';
    }
}
728x90

댓글