본문 바로가기

C++/백준

[C++][백준] 4948 베르트랑 공준

https://www.acmicpc.net/problem/4948

 

4948번: 베르트랑 공준

문제 베르트랑 공준은 임의의 자연수 n에 대하여, n보다 크고, 2n보다 작거나 같은 소수는 적어도 하나 존재한다는 내용을 담고 있다. 이 명제는 조제프 베르트랑이 1845년에 추측했고, 파프누티 체비쇼프가 1850년에 증명했다. 예를 들어, 10보다 크고, 20보다 작거나 같은 소수는 4개가 있다. (11, 13, 17, 19) 또, 14보다 크고, 28보다 작거나 같은 소수는 3개가 있다. (17,19, 23) n이 주어졌을 때, n보다 크고, 2n보

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을 포함하며, 한 줄로 이루어져 있다. (n ≤ 123456)

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

출력

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

예제 입력 1

1

10

13

100

1000

10000

100000

0

예제 출력 1

1

4

3

21

135

1033

8392

 

풀이

에라토스테네스의 체를 이용해서 푸는 문제이다.

에라토슽네스를 이용해서 소수를 구하고 n보다 크고 2n보다 작은 소수의 개수를

카운트하여 출력하면 된다.

 

에라토스테네스의 체란 소수를 찾는 방법으로  고대 그리스 수학자 에라토스테네스가 발견하였다.

알고리즘

  1. 2부터 소수를 구하고자 하는 구간의 모든 수를 나열한다. 그림에서 회색 사각형으로 두른 수들이 여기에 해당한다.
  2. 2는 소수이므로 오른쪽에 2를 쓴다. (빨간색)
  3. 자기 자신을 제외한 2의 배수를 모두 지운다.
  4. 남아있는 수 가운데 3은 소수이므로 오른쪽에 3을 쓴다. (초록색)
  5. 자기 자신을 제외한 3의 배수를 모두 지운다.
  6. 남아있는 수 가운데 5는 소수이므로 오른쪽에 5를 쓴다. (파란색)
  7. 자기 자신을 제외한 5의 배수를 모두 지운다.
  8. 남아있는 수 가운데 7은 소수이므로 오른쪽에 7을 쓴다. (노란색)
  9. 자기 자신을 제외한 7의 배수를 모두 지운다.
  10. 위의 과정을 반복하면 구하는 구간의 모든 소수가 남는다.

그림의 경우, {\displaystyle 11^{2}>120} 이므로 11보다 작은 수의 배수들만 지워도 충분하다. 즉, 120보다 작거나 같은 수 가운데 2, 3, 5, 7의 배수를 지우고 남는 수는 모두 소수이다.

 

(출처:  위키백과 https://ko.wikipedia.org/wiki/%EC%97%90%EB%9D%BC%ED%86%A0%EC%8A%A4%ED%85%8C%EB%84%A4%EC%8A%A4%EC%9D%98_%EC%B2%B4)

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#include <stdlib.h>
#define MAX 123456*2+1
 
int main(){
    int a;
    int min[MAX];
 
    for(int i=2; i<MAX; i++)
        min[i]=i;
    //에라토스테네스의 체
    for(int i=2; i*i<MAX; i++){
        if(min[i]==i){
            for(int j=i*i; j<MAX; j+=i){
                if(min[j]==j)
                    min[j]=i;
            }
        }
    }
 
    while(true){
        int count =0;
        scanf("%d",&a);
        if(a==0)    break;
        for(int i=a+1; i<=2*a; i++)
            if(min[i]==i)    count++;
        printf("%d\n",count);
    }
 
}
 

 

'C++ > 백준' 카테고리의 다른 글

[C++][백준] 5622 다이얼  (0) 2020.03.11
[C++][백준] [정렬] 5544 리그  (0) 2020.03.11
[C++][백준] 4673 셀프 넘버  (0) 2020.03.10
[C++][백준] 4344 평균은 넘겠지  (0) 2020.03.10
[C++][백준] 3052 나머지  (0) 2020.03.10