목차
1. 문제
https://www.acmicpc.net/problem/9764
문제
양의 정수 N (1 ≤ N ≤ 2000)을 서로 다른 자연수의 합으로 나타내는 방법은 여러 가지가 있다. 예를 들어:
- N = 5인 경우
- 5
- 1 + 4
- 2 + 3 (총 3가지)
- N = 6인 경우
- 6
- 1 + 5
- 2 + 4
- 1 + 2 + 3 (총 4가지)
N이 주어졌을 때, 서로 다른 자연수의 합으로 나타내는 방법의 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에, 테스트 케이스의 개수 T (1 ≤ T ≤ 20)이 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, N이 주어진다.
출력
각 테스트 케이스마다 N을 서로 다른 자연수의 합으로 나타내는 방법의 수 100999로 나눈 나머지를 출력한다.
2. 풀이
📌 문제의 핵심 분석
- 자연수는 중복 사용할 수 없다.
- 조합의 순서가 달라도 같은 것으로 취급한다.
- 즉, 중복 없는 조합(Combination)을 구하는 문제이다.
📌 DP(동적 프로그래밍) 접근법
이 문제는 대표적인 DP 문제로 접근할 수 있다. DP를 사용하는 이유는:
- 문제를 작은 부분 문제로 나눌 수 있다.
- 부분 문제의 답을 이용해 큰 문제를 해결할 수 있다.
- 중복 계산을 방지하여 효율적이다.
📌 DP 배열 정의
- dp[i]: "서로 다른 자연수의 합으로 숫자 i를 만드는 경우의 수"
- 초기 상태: dp[0] = 1 (합이 0인 경우를 하나로 간주)
📌 상태 전이 규칙
숫자 k를 한 번만 사용하는 것을 보장하기 위해, 역순으로 DP 배열을 업데이트한다:
dp[i] = (dp[i] + dp[i - k]) % mod;
이때 mod는 100999로 나눈 나머지를 의미한다.
📌 예시 (N = 6)
- 초기 배열 상태:
dp = [1, 0, 0, 0, 0, 0, 0]
- 숫자 1, 2, 3, 4, 5, 6을 차례로 사용하여 배열을 업데이트한 결과:
최종 dp = [1, 1, 1, 2, 2, 3, 4]
- 따라서,
dp[6] = 4
(답)
3. 코드 구현
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine());
int[] arr = new int[T];
int max = 0;
for (int i = 0; i < T; i++) {
arr[i] = Integer.parseInt(br.readLine());
max = Math.max(max, arr[i]);
}
int mod = 100999;
int[] dp = new int[max + 1];
dp[0] = 1;
for (int k = 1; k <= max; k++) {
for (int i = max; i >= k; i--) {
dp[i] = (dp[i] + dp[i - k]) % mod;
}
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < T; i++) {
sb.append(dp[arr[i]]).append("\n");
}
System.out.println(sb);
}
}
4. 정리
📌 시간 복잡도 분석
- 시간 복잡도: O(N²)
- 공간 복잡도: O(N)
📌 주의할 점
- dp[i] 접근 시 인덱스 실수 주의 (dp[arr[i]]로 접근해야 한다).
- 최초 dp[i]로 작성하여 실수를 함 - 입력이 여러 개인 경우, 최대값을 구해 미리 DP 배열을 채우는 방식으로 최적화한다.
- 테스트 케이스 마다 dp[]를 새로 생성하여 사용 했을때는 132ms으로 나왔고
최대값을 구해 하나의 dp[]만 사용했을때 100ms으로 개선되었다
📌 결론
이 문제를 통해 DP의 기본적인 사용법과 배열을 최적화하여 사용하는 방식을 배울 수 있다. 이 개념은 다른 유사한 DP 문제에도 효과적으로 적용할 수 있다.
'Java > 알고리즘(코테)' 카테고리의 다른 글
List(리스트) (0) | 2025.04.29 |
---|---|
Array(배열) (0) | 2025.04.28 |
백준 32394번 4-cycle (그래프 활용) (0) | 2025.03.18 |
백준 기록 (solved.ac) + 프로그래머스 기록 (5) | 2025.02.04 |
백준 7662번 : 이중 우선순위 큐 (TreeMap 활용) (0) | 2025.01.09 |