🔗 문제
2960번: 에라토스테네스의 체
2, 4, 6, 8, 10, 3, 9, 5, 7 순서대로 지워진다. 7번째 지워진 수는 9이다.
www.acmicpc.net
level : 실버 4
문제 설명:
에라토스테네스의 체는 N보다 작거나 같은 모든 소수를 찾는 유명한 알고리즘이다.
N, K가 주어졌을 때, K번째 지우는 수를 구하는 프로그램을 작성하시오.
1. 2부터 N까지 모든 정수를 적는다.
2. 아직 지우지 않은 수 중 가장 작은 수를 찾는다. 이것을 P라고 하고, 이 수는 소수이다.
3. P를 지우고, 아직 지우지 않은 P의 배수를 크기 순서대로 지운다.
4. 아직 모든 수를 지우지 않았다면, 다시 2번 단계로 간다.
🔮 풀이 아이디어
에라토스테네스의 체 알고리즘을 알고 있어서 먼저 함수로 작성 후에 코드를 문제에 맞게 수정하였다.
sieve라는 해당 인덱스의 소수 여부를 담고 있는 리스트를 선언해 준 후
에라토스테네스의 체 알고리즘을 통해 1~N까지의 수 중 소수만 남긴다.
여기서는 K번째 지워지는 수를 구하는 프로그램이기 때문에
반복문을 돌면서 소수에 해당하는 수, 그리고 지워지는 수를 차례대로 담은 리스트 order를 반환한다.
에라토스테네스의 체 알고리즘은 시간 복잡도를 줄이기 위해 반복문을 int(N ** 0.5)까지 돌리게 된다. 만약 N이 120이라면 11 * (2 ~ 10)까지는 이전 반복문에서 확인이 가능하기 때문에 11의 제곱인 121부터 검사를 해야 하는데 121은 120보다 작아 범위에 포함되지 않아서 검사할 필요가 없기 때문이다.
이러한 방식의 코드에서 수정했기 때문에 m + 1 이상인 소수가 order에 담기지 않아 따로 추가해 주었다.
order.extend([i for i in range(m + 1, N + 1) if sieve[i] is True])
원래 cnt라는 카운트 변수를 두어 시간을 줄이려고 했으나,
K, N의 범위가 1 ≤ K < N, max(1, K) < N ≤ 1000 로 주어져있고
현재 코드에서 if cnt == K: break 부분이 2번 들어가면서 코드가 길어지기 때문에 배열에 담는 방식을 선택했다.
최종 제출 코드
def order_of_erasing(N):
sieve = [True] * (N + 1) # 체
order = [] # 지워지는 순서
m = int(N ** 0.5) # 마지막 체크 범위 구하기
for i in range(2, m + 1):
if sieve[i] is True:
order.append(i)
for j in range(i + i, N + 1, i):
if sieve[j] is True:
sieve[j] = False
order.append(j)
# 이후 추가되지 않은 소수들 포함하기
order.extend([i for i in range(m + 1, N + 1) if sieve[i] is True])
return order
N, K = map(int, input().split())
print(order_of_erasing(N)[K - 1])
📝 새로 공부한 내용
n, k = map(int, input().split())
num = [1] * (n + 1)
for i in range(2, n + 1):
if num[i] == 0: continue
if k == 0: break
for j in range(i, n + 1, i):
if num[j]:
num[j] = 0
k -= 1
if k == 0:
print(j)
break
다른 분의 풀이를 보면서 위에서도 계속 언급했듯이 원래 알고리즘에서 수정하다 보니 문제에서 요구하는 값만 구하는 데에 불필요한 코드가 포함되었다는 것을 느꼈다.
이 문제에서 소수 또한 지워지는 값이기 때문에 코드의 11번째 줄인 2번째 반복문에 포함되어서 작성이 가능하다는 것을 알 수 있다.
그리고 K번째를 직접 카운트하여 시간 또한 줄이는 방향으로 깔끔하게 코드를 짤 수 있지 않았을까 하는 아쉬움이 든다..!
📚 참고
'study > 알고리즘' 카테고리의 다른 글
[알고리즘/백준] 2659번 - 십자카드 문제 (0) | 2023.07.06 |
---|---|
[알고리즘/백준] 26069번 - 붙임성 좋은 총총이 (0) | 2023.05.31 |
[알고리즘/백준] 1912번 - 연속합 (0) | 2023.05.13 |
[알고리즘/백준] 1967번 - 트리의 지름 (2) | 2022.11.03 |
[알고리즘] 3-Way inPlaceQuickSort - 네덜란드 국기 알고리즘 (0) | 2022.10.05 |