지원이에게 2진 수열을 가르쳐 주기 위해, 지원이 아버지는 그에게 타일들을 선물해주셨다. 그리고 이 각각의 타일들은
0
또는1
이 쓰여 있는 낱장의 타일들이다.
어느 날 짓궂은 동주가 지원이의 공부를 방해하기 위해 0이 쓰여진 낱장의 타일들을 붙여서 한 쌍으로 이루어진00
타일들을 만들었다. 결국 현재 1 하나만으로 이루어진 타일 또는 0타일을 두 개 붙인 한 쌍의 00타일들만이 남게 되었다.
그러므로 지원이는 타일로 더 이상 크기가 N인 모든 2진 수열을 만들 수 없게 되었다. 예를 들어, N=1일 때 1만 만들 수 있고, N=2일 때는 00, 11을 만들 수 있다. (01, 10은 만들 수 없게 되었다.) 또한 N=4일 때는 0011, 0000, 1001, 1100, 1111 등 총 5개의 2진 수열을 만들 수 있다.
우리의 목표는 N이 주어졌을 때 지원이가 만들 수 있는 모든 가짓수를 세는 것이다. 단 타일들은 무한히 많은 것으로 가정하자.
첫 번째 줄에 자연수 N이 주어진다. (1 ≤ N ≤ 1,000,000)
첫 번째 줄에 지원이가 만들 수 있는 길이가 N인 모든 2진 수열의 개수를 15746으로 나눈 나머지를 출력한다.
동적 계획법은 특정 규칙을 담은 점화식을 기준으로 문제를 풀어나가기 때문에 무작위로 써서 규칙을 찾아봤는데,, 개수가 피보나치 수열 형태로 증가하는 걸 발견할 수 있었다!
❌ 어제 풀었던 피보나치 수열 문제와 같이 Bottom-up 접근을 통해 풀었는데 오답 처리가 됐다,,
import java.io.*;
import java.util.*;
public class Main {
static int[] arr;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int n = Integer.parseInt(br.readLine());
arr = new int[n];
bw.write(fibo(n) % 15746 + "");
br.close();
bw.close();
}
static int fibo(int n) {
arr[0] = 1; arr[1] = 2;
for(int i=2;i<n;i++) {
arr[i] = arr[i-1] + arr[i-2];
}
return arr[n-1];
}
}
❌ 혹시나 싶어서 1을 넣어봤는데 인덱스 범위 초과 예외가 발생했다!
n = 1
인 경우에는arr[1]
을 참조할 수 없으므로,n = 1
인 경우에는 1을 리턴할 수 있도록 조건문을 추가해주니 제대로 1을 리턴했으나,, 여전히 오답 처리,,
...
static int fibo(int n) {
if(n == 1) return 1;
arr[0] = 1; arr[1] = 2;
for(int i=2;i<n;i++) {
arr[i] = (arr[i-1] + arr[i-2])
}
return arr[n-1];
}
}
✅ 원인을 도저히 모르겠어서 구글링 해 본 결과 대부분의 사람들이 나머지 연산
% 15746
을 출력문이 아닌 수열을 구하는 과정에서 수행하고 있었다. 솔직히 처음에 문제 봤을 때부터 왜 나머지 연산을 굳이 하나 싶었는데 입력 범위가 1,000,000까지이기 때문에 오버플로우가 발생할 수 있어서 그런 거였다!
애초에 수열을 구할 때 나머지 연산을 수행하면 나머지가 저장되어 오버플로우가 발생하지 않겠지만, 오버플로우가 발생한 상태에 나머지 연산을 수행하면 값이 달라질 수 밖에 없다.
import java.io.*;
import java.util.*;
public class Main {
static int[] arr;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int n = Integer.parseInt(br.readLine());
arr = new int[n];
bw.write(fibo(n) + "");
br.close();
bw.close();
}
static int fibo(int n) {
if(n == 1) return 1;
arr[0] = 1; arr[1] = 2;
for(int i=2;i<n;i++) {
arr[i] = (arr[i-1] + arr[i-2]) % 15746;
}
return arr[n-1];
}
}