일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- 다이나믹 프로그래밍
- springboot
- 정수론
- 백준
- 알고리즘
- SWEA
- MYSQL
- 스택
- 문자열
- dfs
- 정보처리기사
- DB
- 수학
- 구현
- 소수 판정
- n과 m
- 그래프 탐색
- Spring Security
- 프로그래머스
- 프로젝트
- 너비 우선 탐색
- Vue
- JPA
- 깊이 우선 탐색
- 재귀
- 백트래킹
- 브루트포스 알고리즘
- 자료 구조
- 그래프 이론
- 배포
- Today
- Total
영원히 남는 기록, 재밌게 쓰자
백준 [15990] 1, 2, 3 더하기 5 (자바) 본문
문제
입력
첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, 정수 n이 주어진다. n은 양수이며 100,000보다 작거나 같다.
출력
각 테스트 케이스마다, n을 1, 2, 3의 합으로 나타내는 방법의 수를 1,000,000,009로 나눈 나머지를 출력한다.
풀이
예시에서 4를 만드는 경우를 보면 3을 만드는 경우의 수에서 1을 붙여서 만들 수 있다.
3을 만드는 케이스에서 1을 붙여서 4를 만드는 경우
1+2+1
2+1+1 -> 같은 수를 2번 이상 사용한 경우라서 경우의 수에 포함되지 않는다.
3+1
2를 만드는 케이스에서 2를 붙여서 4를 만드는 경우
2+2 같은 수를 두 번 붙여 포함 x
1을 만드는 케이스에서 3을 붙여서 4를 만드는 경우
1+3
4를 만드는 경우의 수는 2차원 배열을 이용해서 표현할 수 있다.
끝이 1로 끝나는 연산의 경우의 수가 2개 -> dp[4][1] = 2
끝이 2로 끝나는 연산의 경우의 수가 0개 -> dp[4][2] = 0
끝이 3로 끝나는 연산의 경우의 수가 1개 -> dp[4][3] = 1
총 3개이다.
이와 같이 5를 적용해보면
(5를 만드는 케이스 중 1로 끝나는 연산의 경우는) = (4를 만드는 연산 뒤에 1로 끝나지 않는 경우의 연산에서 1를 붙인 케이스의 경우들)
dp[5][1] = dp[4][2] + dp[4][3] = 0+1 = 1 (1+3+1)
(5를 만드는 케이스 중 2로 끝나는 연산의 경우는) = (3을 만드는 연산 뒤에 2로 끝나지 않는 경우의 연산에서 2를 붙인 케이스의 경우들)
dp[5][2] = dp[3][1] + dp[3][3] = 1+1 = 2 (2+1+2, 3+2)
(5를 만드는 케이스 중 3으로 끝나는 연산의 경우는) = (2을 만드는 연산 뒤에 3으로 끝나지 않는 경우의 연산에서 3을 붙인 케이스의 경우들)
dp[5][3] = dp[2][1] + dp[2][2] = 0+1 = 1 (2+3)
그럼 5를 만드는 경우의 수 중 같은 수를 연속해서 사용하지 않고 연산이 가능한 경우는 3가지 케이스의 합인 4가 된다.
점화식
dp[i][1] = dp[i-1][2] + dp[i-1][3]
dp[i][2] = dp[i-2][1] + dp[i-2][3]
dp[i][3] = dp[i-3][1] + dp[i-3][2]
마지막에 한번 더 1000000009 값을 나눠주는 이유를 몰랐는데 찾아보니 중간 연산에서 dp[N][1],dp[N][2],dp[N][3]의 값이 1000000009보다 클 수 있어서 오버플로우 방지를 위해 한번 더 나눠줌으로서 나머지 값이 1000000009로 나눌 수 있는 범위를 보장한다고 한다.
정답코드
package com.baekjoon.p15990;
import java.io.*;
public class Main {
static final int num = 100001;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
long[][] dp = new long[num][4];
dp[1][1] = 1;
dp[2][2] = 1;
dp[3][1] = 1;
dp[3][2] = 1;
dp[3][3] = 1;
for (int i = 4; i < num; i++) {
dp[i][1] = ((dp[i - 1][2]) + (dp[i - 1][3])) % 1_000_000_009;
dp[i][2] = ((dp[i - 2][1]) + (dp[i - 2][3])) % 1_000_000_009;
dp[i][3] = ((dp[i - 3][1]) + (dp[i - 3][2])) % 1_000_000_009;
}
int T = Integer.parseInt(br.readLine());
StringBuilder sb = new StringBuilder();
while (T-- > 0) {
int N = Integer.parseInt(br.readLine());
long ans = (dp[N][1] + dp[N][2] + dp[N][3]) % 1_000_000_009;
sb.append(ans).append("\n");
}
System.out.print(sb);
}
}
'Algorithm > 백준' 카테고리의 다른 글
백준 [2156] 포도주 시식 (자바) (0) | 2024.05.27 |
---|---|
백준 [2961] 도영이가 만든 맛있는 음식 (자바) (0) | 2024.05.24 |
백준 [1138] 한 줄로 서기 (자바) (0) | 2024.05.21 |
백준 [17103] 골드바흐 파티션 (자바) (0) | 2024.05.20 |
백준 [2477] 참외밭 (자바) (0) | 2024.05.19 |