오늘 푼 문제는 백준 - 15988번 문제이다. 난이도는 실버2다 !
정수 4를 1, 2, 3의 합으로 나타내는 방법은 총 7가지가 있다. 합을 나타낼 때는 수를 1개 이상 사용해야 한다.
정수 n이 주어졌을 때, n을 1, 2, 3의 합으로 나타내는 방법의 수를 구하는 프로그램을 작성하시오.
첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, 정수 n이 주어진다. n은 양수이며 1,000,000보다 작거나 같다.
각 테스트 케이스마다, n을 1, 2, 3의 합으로 나타내는 방법의 수를 1,000,000,009로 나눈 나머지를 출력한다.
3
4
7
10
7
44
274
문제의 분류가 DP라는 것을 보자마자 쉽게 방법이 떠올랐다. 일단 문제에서 3까지만 사용한다는 것도 힌트가 되었다. ( 분류를 안 봤으면 이렇게 금방 못 풀었을 것 같기도 하다.. ! 이제 분류를 보지 않고 문제를 풀어봐야겠다 ! 진짜 못 풀겠을 때 힌트삼아 확인하기.. )
먼저 예제에 있는 7로 설명을 해보려고 한다. 7은 6+1이자, 5+2이자, 4+3이다. 그러므로 4, 5, 6을 만들 수 있는 경우의 수들이 구해져있다면, 각 경우들에 1, 2, 3을 더하면 되기 때문에, 각 경우의 수들의 합이 7의 경우의 수일 것이다. 이것이 곧 점화식 !!
해당 문제는 1-3을 이용해서 만들 수 있는 경우의 수를 구하는 것이므로, 초기값을 아래와 같이 3까지 구해둬야 한다.
위에 설명한 내용을 점화식으로 나타내면 아래와 같다.
이렇게 초기값과 점화식을 구하면 사실 DP 문제는 다 풀었다고 볼 수 있다 ~ 아래의 코드를 보면 된다 ~
또 이 문제에서 주의해야 할 것은, 문제에서 1,000,000,009로 나눈 값을 출력하라는 것 부터 힌트가 되지만, 각 경우의 수들이 int 범위를 넘어갈 수 있다. 그래서 점화식 결과 값을 저장하는 배열은 long 타입으로 해주었고, 저장할 때 Mod 연산을 수행한 후 저장해주었다 ~~
import java.io.*;
import java.util.*;
public class Main {
static class Solution{
private static int MAX = 1000000;
private static int MOD = 1000000009;
private long[] results;
Solution(){
results = new long[MAX+1];
Arrays.fill(results, -1);
results[1] = 1;
results[2] = 2;
results[3] = 4;
}
void init(){
for(int i=4; i<=MAX; i++){
results[i] = (results[i-1]+results[i-2]+results[i-3])%MOD;
}
}
long solution(int n){
return results[n];
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // reader
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); // writer
int n = Integer.parseInt(br.readLine());
Solution solution = new Solution();
solution.init();
for(int i=0; i<n; i++){
bw.write(solution.solution(Integer.parseInt(br.readLine())) + "\n");
}
bw.flush(); // flush
bw.close(); // close
br.close(); // close
}
}