[필수 문제] 숫자 만들기

2021. 2. 15. 01:52코딩 테스트/필수 문제

1. 문제

숫자 1, 2, 3을 이용하여 숫자 N을 만드는 경우의 수를 출력하는 프로그램을 작성하시오. 예를 들어, N이 4일 경우에는 다음의 7가지 경우가 존재한다. 단, 경우의 수가 매우 많을 수 있으므로, 경우의 수를 1,000,007 로 나눈 나머지를 출력한다.

1+1+1+1
1+1+2
1+2+1
2+1+1
2+2
1+3
3+1


입력

첫 번째 줄에 N이 주어진다. ( 1 ≤ N ≤ 100,000 ) 

출력

1, 2, 3을 이용하여 N을 만들 수 있는 경우의 수를 1,000,007 로 나눈 나머지를 출력한다. 

예제 입력

case 1) 4

case 2) 200

예제 출력

case 1) 7

case 2) 290816

 

 

 

2. 풀이

숫자 만들기는 동적 계획법을 이용해야 해결이 가능한 문제이다.

 

동적 계획법에서 가장 중요한 요소는 과연 이 문제가 동적 계획법을 이용해야하는지 아닌지 판별하는 것이라고 생각한다. 우선 가장 중요한 패턴을 찾아보면 된다.

 

n = 4일 경우, 총 7개의 경우의 수가 나온다.

  • 1 + 1 + 1 + 1
  • 1 + 1 + 2
  • 1 + 2 + 1
  • 2 + 1 + 1
  • 2 + 2
  • 1 + 3
  • 3 + 1

 

여기서 패턴은 한번에 찾기 힘들지만, 가장 마지막 요소가 동일한 것 끼리 묶어보면 힌트가 보인다.

1 + 1 + 1 + 1
1 + 2 + 1
2 + 1 + 1
3 + 1
1 + 1 + 2
2 + 2
1 + 3
3 + 1 2 + 2 1 + 3
n = 3인 경우의 수 = 4개 n = 2인 경우의 수 = 2개 n = 1인 경우의 수 = 1개
즉, T(4) = T(4 - 1) + T(4 - 2) + T(4 - 3)

이를 공식화한다면 T(i) = T(i - 1) + T(i - 2) + T(i - 3) + ... T(i - m)이 된다. 그리고 이 특징은 전형적인 피보나치 수 구하는 문제와 동일하다는 것을 확인할 수 있다. 이를 코드화하면 다음과 같다.

import java.io.*;

public class Main {

    private static final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    private static final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

    private static int n;
    private static int[] arr;

    public static void main(String[] args) throws IOException {

        n = Integer.parseInt(br.readLine());
        arr = new int[n+1];

        /*
        T(1) = 1 (1)
        T(2) = 2 (1+1, 2)
        T(3) = 4 (1+1+1, 1+2, 2+1, 3) = 끝이 1인 경우의 수(2) + 끝이 2인 경우의 수(1) + 끝이 3인 경우의 수(1)
        T(4) = 1 + 2 + 4 + 끝이 4인 경우의 수(1) = 7
         */
        arr[1] = 1;
        int sum = 0;
        for(int i = 2; i <= 3; i++) {
            sum += arr[i-1];
            arr[i] = sum + 1;
        }

        for(int i = 4; i <= n; i++) {
            for(int j = i-3; j <= i-1; j++) {
                arr[i] = (arr[i] + arr[j]) % 1000007;
            }
        }
        
        bw.write(arr[n] + "");

        br.close();
        bw.flush();
        bw.close();
    }

}
728x90

'코딩 테스트 > 필수 문제' 카테고리의 다른 글

[필수 문제] 웜 바이러스  (0) 2021.02.15
[필수 문제] 이분 그래프 판별  (0) 2021.02.15
[필수 문제]피보나치 수  (0) 2021.02.15
[필수 문제] goodseq  (0) 2021.02.15