I'm FanJae.
[Codeup] 3733. 우박수 길이 (3n+1) (Large) 본문
1. 문제 링크
https://codeup.kr/problem.php?id=3733
코드업
코드업은 프로그래밍을 배우고 싶은 사람들을 위한 온라인 학습 플랫폼입니다.
codeup.kr
2. 문제 풀이
1 <= a <= b <= 10,000,000 으로 상당히 크다. 중간 과정을 생략하기 위한 계산이 필요하다.
지나온 경로에 대한 계산을 위해 재귀 탐색을 진행하였고, 메모이제이션으로 값을 계산해두어 연산 횟수를 줄였다.
3. 아이디어
1. 이 문제의 핵심은 각 시작 수마다 1까지 직접 계산하면 중복 연산이 많이 발생한다는 점이다.
2. 따라서 어떤 수 n에서 1까지 도달하는 수열의 길이 length[n]을 저장해둔다.
3. 연산 과정에서 같은 n을 다시 만나면 저장된 값을 재사용한다.
4. 단, 수열을 앞에서부터 진행하는 동안에는 중간값의 length가 아직 확정되지 않는다.
4-1. 반복문으로 구현한다면 지나온 경로를 path에 저장한 뒤, 이미 계산된 값을 만났을 때 역순으로 length를 채워야 한다.
4-2. 재귀로 구현하면, 호출 과정에서 반환 해주는 것으로 path 역할을 해줄 수 있다. 즉, return 과정에서 length[n] = length[next] + 1 형태로 자연스럽게 메모이제이션이 가능하다.
5. 중간 값이 커질 수 있으므로, long long int를 사용하고, 메모리 크기 제한을 고려하여, LIMIT를 두어 배열 범위 안의 값만 캐싱해 준다.
4. 구현
※ C++ Source Code
더보기
#include <iostream>
#define LIMIT 10000000
using namespace std;
int length[LIMIT];
int three_n(long long int in)
{
if (in < LIMIT && length[in] != 0) // 계산됨.
{
return length[in];
}
long long int next_value;
if (in % 2 == 1) next_value = 3 * in + 1;
else next_value = in / 2;
int result = three_n(next_value) + 1;
if (in < LIMIT)
{
length[in] = result;
}
return result;
}
int main(void)
{
int n;
int a, b;
int temp;
int ans_number = 0;
int ans_length = 0;
length[1] = 1; // 1의 수열의 길이
cin >> a >> b;
for (int i = a; i <= b; i++)
{
temp = three_n(i);
if (temp > ans_length)
{
ans_number = i;
ans_length = temp;
}
}
cout << ans_number << " " << ans_length;
}
'Codeup' 카테고리의 다른 글
| [Codeup] 2748. 덧셈, 뺄셈으로 n만들기 (0) | 2026.05.03 |
|---|---|
| [Codeup] 2634. 거스름돈 II (0) | 2026.05.02 |
| [Codeup] 3703. 사탕 줍기 1 (0) | 2026.05.01 |
| [Codeup] 4701. 두 용액 (0) | 2026.04.30 |
| [Codeup] 1476. 2차원 배열 빗금 채우기 3-1 (0) | 2026.04.20 |
Comments