소인수분해 했을 경우 나오는 소인수가 2, 3 그리고 5뿐인 수를 이야기
수열로 늘어 놓으면 1, 2, 3, 4, 5, ,6, 8, 9, 10, 12, ...
정수 n이 주어졌을 때, n번째 못생긴 수를 출력하는 프로그램을 작성하시오
- heap을 만들어서 ugly[cnt] 에 못생긴 수를 저장
- 처음 부터 *2, *3, *5 를 해가며 3개의 숫자를 push
- minheap을 사용하여, 가장 작은 수를 pop
- 위의 내용 MAXN까지 반복
#include <stdio.h>
typedef long long LL;
LL heap[5000] = { 0, 1 }, ugly[1600], hcnt = 1; // 첫 힙에 0과 1을 넣어둠
void Swap(int x, int y) { LL z = heap[x]; heap[x] = heap[y]; heap[y] = z; }
void push(int p) // p는 힙의 인덱스
{
if (p <= 1 || heap[p / 2] <= heap[p]) return; // 0보다 작거나, 부모가 더 작거나 같으면 변경 안함
Swap(p / 2, p); // 변경
push(p / 2); // 자리를 찾아감
}
void pop(int p)
{
int np = p * 2; // 자식과 비교
if (np > hcnt) return; // 자식이 없으면
if (np < hcnt && heap[np] > heap[np + 1]) np++; // 자식이 있고, 왼쪽 자식이 더 크면, 작은 것을 가지고 놀아야 하므로++
if (heap[p] <= heap[np]) return; // 변경하지 않아도 되면 return
Swap(p, np); // 변경
pop(np); // 재귀로
}
int main()
{
int n, cnt = 1;
while (cnt <= 1500) {
ugly[cnt] = heap[1]; // ugly 첫 번째 요소는 1
heap[1] = heap[hcnt--]; // 젤 마지막 인덱스 것을 젤 위로 올리고
pop(1);
if (ugly[cnt] == ugly[cnt - 1]) // 동등한 것이 들어올 경우
continue;
heap[++hcnt] = ugly[cnt] * 2; push(hcnt); // 2,3,5 를 곱하면 ugly 숫자가 나옴
heap[++hcnt] = ugly[cnt] * 3; push(hcnt);
heap[++hcnt] = ugly[cnt] * 5; push(hcnt);
cnt++;
}
while (1) {
scanf("%d", &n);
if (n == 0) break;
printf("%lld\n", ugly[n]);
}
return 0;
}
1 2 9 0 |
1 2 10 |
'Algorithms > simulation' 카테고리의 다른 글
2 Problem A : 수열 (0) | 2019.11.07 |
---|---|
1 Problem F : 연속부분합 찾기 (0) | 2019.11.07 |
4 Problem C : 숫자 야구2 (0) | 2019.11.07 |
4 Problem B : 타일 채우기 (0) | 2019.11.07 |
4 Problem A : 책 복사하기 (0) | 2019.11.07 |
댓글