[백준] 4948번 :베르트랑 공준 - Python 파이썬
알고리즘 분류:
링크: https://www.acmicpc.net/problem/4948
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
제출한 답
while True:
n = int(input())
if n == 0: break
arr = [False,False] + [True]* (2*n-1)
for i in range(2,int((2*n)**0.5)+1):
if arr[i] == True:
for k in range(i,2*n+1,i):
arr[k] = False
print(arr[n+1:2*n+1].count(True))
처음엔 이렇게 평소처럼 에라토스테네스의체, 제곱근 등을 이용해 문제를 풀었다.
맞았지만 시간이 3000ms 넘게 나왔다.
생각해보니 while문 속에서 요청이 엄청 많이 들어오면,
그때마다 소수 개수를 다시 계산해야 된다.
비효율적인 것 같아서 아예 처음부터 범위(1~123456)내의 소수 여부를 미리 배열에 저장해놨다.
import sys
import math
MAX = 123456
#최댓값까지의 범위 내 소수 미리 arr에 모아놓기
#by 에라토스테네스의 체
arr = [0,0] + [1] * (2*MAX-1) #0,1은 소수 false-> 0
for i in range(2,int(math.sqrt(2*MAX))+1):
if arr[i]:
for k in range(2*i,2*MAX+1,i):
arr[k] = 0
#반복적으로 소수 개수 구하기
while True:
n = int(sys.stdin.readline())
if n == 0: break
#arr 안 값들을 boolean 대신 0,1로 넣으면
#count 대신 sum을 쓸 수 있고 조금 더 빠르다..
print(sum(arr[n+1:2*n+1]))
추가적으로 sys.stdin.readline()과 math.sqrt를 통해
시간 줄이기 눈물의 똥꼬쇼...
arr안에도 불린 대신 0,1을 넣어
나중에 범위 내 소수의 개수를 sum을 통해 계산할 수 있게 했다.
이로써 실행시간 190ms대 달성함.
앞으로도 while문 반복실행이 필요한 문제는
경우에 따라 미리 base값을 계산해 넣는 게 좋은지 잘 판단해야 겠다.
'알고리즘' 카테고리의 다른 글
[백준] 1085번 :직사각형에서 탈출- 파이썬 (0) | 2021.08.25 |
---|---|
[백준] 9020번 :골드바흐의 추측 - Python 파이썬 (0) | 2021.08.25 |
[백준] 1929번 :소수 구하기 - Python 파이썬 (0) | 2021.08.25 |
[백준] 11653번 :소인수분해 - Python 파이썬 (0) | 2021.08.24 |
[백준] 2581번 :소수 - Python 파이썬 (0) | 2021.08.24 |