장 준
씨포유
장 준
전체 방문자
오늘
어제
  • 분류 전체보기 (91)
    • 프로그래밍언어 (15)
      • c언어 (10)
      • 파이썬 (0)
      • 자바스크립트 (5)
    • PS (58)
      • 알고리즘 이론 (18)
      • 프로그래머스 (5)
      • 백준 (35)
    • CS (16)
      • 자료구조 (5)
      • 운영체제 (3)
      • 네트워크 (5)
      • 데이터베이스 (0)
      • 기초 지식 (3)
    • 브랜드 (1)

블로그 메뉴

  • 태그

인기 글

태그

  • Implementation
  • 씨포유
  • BFS
  • DFS
  • nodejs
  • 자료구조
  • bitmask
  • 알고리즘
  • 코딩테스트
  • Priority Queue
  • JS
  • PS
  • recursion
  • Stack
  • JavaScript
  • 파이썬
  • 프로그래밍언어
  • 백준
  • 자바스크립트
  • Visual Studio
  • Kruskal algorithm
  • C
  • CS
  • 프로그래머스
  • pypy3
  • Network
  • DP
  • 기초 지식
  • codesandbox
  • python3

최근 댓글

최근 글

hELLO · Designed By 정상우.
장 준

씨포유

[백준(BOJ)] #2014- 소수의 곱 (파이썬, PyPy3)
PS/백준

[백준(BOJ)] #2014- 소수의 곱 (파이썬, PyPy3)

2022. 11. 12. 18:54
728x90

문제

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

 

2014번: 소수의 곱

첫째 줄에 K(1 ≤ K ≤ 100), N(1 ≤ N ≤ 100,000)이 주어진다. 다음 줄에는 K개의 소수가 오름차순으로 주어진다. 같은 소수가 여러 번 주어지는 경우는 없으며, 주어지는 소수는 모두 541보다 작거나

www.acmicpc.net

 


문제 풀이

우선순위 큐를 사용해 문제를 해결할 수 있습니다.

 

2022.07.19 - [CS/자료구조] - [파이썬으로 배우는 자료구조] 우선순위 큐(Priority Queue), 힙(Heap)

 

[파이썬으로 배우는 자료구조] 우선순위 큐(Priority Queue), 힙(Heap)

우선순위 큐(Priority Queue)란? 일반적인 큐(Queue) 자료구조는 FIFO 구조라는 것을 배웠습니다. 큐 배우기 --> 2022.06.29 - [CS/자료구조] - [파이썬으로 배우는 자료구조] 스택(Stack), 큐(Queue) [파이썬으로

c4u-rdav.tistory.com

 

기존 풀이

 

1) 입력받은 소수 리스트를 a에 저장하고, 소수 리스트로 구성된 heap 준비
2) heap에서 pop을 하여 t를 얻음
3) t가 이미 처리된 숫자이면 4) 과정 생략 (카운트 세지 않음)
4) a에 저장된 소수들을 순회하면서 t를 곱하여 얻은 수들을 heap에 저장
5) 2) ~ 4) 과정을 N번 반복하고 마지막에 pop 한 숫자가 N번째 오는 숫자가 됨

입력받은 소수들과 우선순위 큐에 저장된 숫자들을 모두 곱하여 얻을 수 있는 숫자들을 순서대로 구하고, N번 반복하여 N번째 오는 숫자를 구하는 것입니다. 

 

세 소수 2, 5, 7을 입력받아 7번째 숫자를 구하는 과정을 함께 봐보겠습니다.

 

 

1) 힙 [2, 5, 7]에서 pop -> 1번째 숫자 = 2 -> 2 x [2, 5, 7] = [4, 10, 14] -> 힙에 push -> 힙 = [4, 7, 5, 10, 14]

 

2) 힙 [4, 7, 5, 10, 14]에서 pop -> 2번째 숫자 = 4 -> 4 x [2, 5, 7] = [8, 20, 28] -> 힙에 push -> 힙 = [5, 7, 14, 10, 8, 20, 28]

 

3) 힙 [5, 7, 14, 10, 8, 20, 28]에서 pop -> 3번째 숫자 = 5 -> 5 x [2, 5, 7] = [10, 25, 35] -> 힙에 push -> 힙 = [7, 8, 10, 10, 28, 20, 14, 25, 35]

 

4) 힙 [7, 8, 10, 10, 28, 20, 14, 25, 35]에서 pop -> 4번째 숫자 = 7 -> 7 x [2, 5, 7] = [14, 35, 49] -> 힙에 push -> 힙 = [8, 10, 10, 14, 28, 20, 14, 35, 25, 35, 49]

 

5) 힙 [8, 10, 10, 14, 28, 20, 14, 35, 25, 35, 49]에서 pop -> 5번째 숫자 = 8 -> 8 x [2, 5, 7] = [16, 40, 56] -> 힙에 push -> 힙 = [10, 10, 14, 14, 16, 20, 49, 35, 25, 35, 28, 40, 56]

 

6) 힙 [10, 10, 14, 14, 16, 20, 49, 35, 25, 35, 28, 40, 56]에서 pop -> 6번째 숫자 = 10 -> 10 x [2, 5, 7] = [20, 50, 70] -> 힙에 push -> 힙 = [10, 14, 14, 25, 16, 20, 49, 35, 56, 35, 28, 40, 20, 50, 70]

 

7) 힙 [10, 14, 14, 25, 16, 20, 49, 35, 56, 35, 28, 40, 20, 50, 70]에서 pop -> 10은 이미 처리된 숫자이므로 생략 -> 힙 = [14, 14, 20, 25, 16, 20, 49, 35, 56, 35, 28, 40, 70, 50]

 

8) 힙 [14, 14, 20, 25, 16, 20, 49, 35, 56, 35, 28, 40, 70, 50]에서 pop -> 7번째 숫자 = 14 -> 14 x [2, 5, 7] = [28, 70, 98] -> 힙에 push -> 힙 = [14, 16, 20, 25, 28, 20, 28, 35, 56, 35, 50, 40, 70, 49, 70, 98]

 

9) 7번째 숫자는 14

 

개선된 풀이

저의 원래 풀이는 결과는 맞지만 비효율적인 풀이입니다. 무작정 힙에 삽입을 하고 힙에서 pop을 하면서 중복 검사를 하는 로직이기 때문이죠. 따라서 다른 풀이들을 참고하여 중복 검사를 미리하고, 중복되는 숫자를 힙에 넣지 않는 방법으로 풀이를 개선했습니다.

 

1) 입력받은 소수 리스트를 a에 저장하고, 소수 리스트로 구성된 heap 준비
2) heap에서 pop을 하여 t를 얻음
3) a에 저장된 소수들을 순회하면서 t를 곱하여 얻은 수들을 heap에 저장
4) heap에 저장하고 다음 소수를 순회하기 전에 t가 현재 소수로 나누어 떨어지면 break
5) 2)~4) 과정을 N번 반복하고 마지막에 pop 한 숫자가 N번째 오는 숫자가 됨

 

 

pop 해서 얻은 숫자 t를 a의 모든 소수와 곱한 값들을 전부 heap에 저장하지 않고, t가 소수와 나누어 떨어지면 더 이상 heap에 저장하지 않습니다. 따라서 위와 같이 heap에 저장된 수가 확연히 적다는 것을 확인할 수 있습니다.

 


구현

기존 코드

import sys
import heapq as hq
input = sys.stdin.readline

if __name__ == "__main__":
    K, N = map(int, input().split())
    a = list(map(int, input().split()))
    heap = [x for x in a]

    cnt = 0
    res = 0

    while cnt < N:
        t = hq.heappop(heap)
        # pop한 값이 이미 처리되지 않았을 경우만
        if t != res:
            res = t
            cnt += 1
            for ai in a:
                hq.heappush(heap, ai * t)

    print(res)

기존 코드 실행 결과

 

개선된 코드

import sys
import heapq as hq
input = sys.stdin.readline

if __name__ == "__main__":
    K, N = map(int, input().split())
    a = list(map(int, input().split()))
    heap = [x for x in a]

    res = 0

    for i in range(N):
        res = hq.heappop(heap)
        for ai in a:
            hq.heappush(heap, ai * res)
            # 중복 검사
            if res % ai == 0:
                break
    print(res)

개선된 코드 실행 결과

메모리와 시간이 확연히 차이 나는 것을 확인할 수 있습니다.

728x90
반응형
저작자표시 (새창열림)

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

[백준(BOJ)] #4485- 녹색 옷 입은 애가 젤다지? (파이썬, PyPy3)  (0) 2022.11.16
[백준(BOJ)] #10026- 적록색약 (파이썬, Python3)  (0) 2022.11.15
[백준(BOJ)] #1507- 궁금한 민호 (파이썬, PyPy3)  (0) 2022.11.11
[백준(BOJ)] #1561- 놀이 공원 (파이썬, PyPy3)  (0) 2022.11.09
[백준(BOJ)] #1562- 계단 수 (파이썬, PyPy3)  (0) 2022.11.08
    'PS/백준' 카테고리의 다른 글
    • [백준(BOJ)] #4485- 녹색 옷 입은 애가 젤다지? (파이썬, PyPy3)
    • [백준(BOJ)] #10026- 적록색약 (파이썬, Python3)
    • [백준(BOJ)] #1507- 궁금한 민호 (파이썬, PyPy3)
    • [백준(BOJ)] #1561- 놀이 공원 (파이썬, PyPy3)
    장 준
    장 준
    C4U(Computer For You)

    티스토리툴바