https://www.acmicpc.net/problem/10425
10425번: 피보나치 인버스
첫 번째 줄에 테스트케이스를 나타내는 T(1 ≤ T ≤ 100)가 입력으로 주어진다. 두 번째 줄부터 각 테스트케이스마다 양의 정수 Fn이 입력으로 주어진다. (1 ≤ Fn ≤ 1021000, 1 ≤ N ≤ 100,000)
www.acmicpc.net
* 문제 요약
피보나치 수는 수학에서 위의 점화식으로 정의되는 수열이다. 피보나치 수는 0과 1로 시작하며, 다음 피보나치 수는 바로 앞의 두 피보나치 수의 합이 된다.
n = 0, 1, ... 에 해당하는 피보나치 수는 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, ... 이다.
프로그래밍 실습에서 문제 중 n을 입력받았을 때 Fn 의 값을 출력하는 문제가 자주 등장한다. 실습을 하고 있던 희원이는 문득 이 문제가 너무 쉽다고 생각했다.
희원이는 실습 도중 반대로 Fn 이 주어졌을 때 n을 출력하는 문제는 어떨지 궁금했다. 피보나치 수 Fn 이 주어졌을 때 출력하는 프로그램을 만들어보자.
* 입력
첫 번째 줄에 테스트케이스를 나타내는 T (1 <= T <= 100) 가 입력으로 주어진다.
두 번째 줄부터 각 테스트케이스마다 양의 정수 Fn 이 입력으로 주어진다. (1 <= Fn <= 10^21000, 1 <= N <= 100,000)
* 출력
피보나치 수 Fn 이 주어졌을 때 n을 출력한다. 만약 가능한 경우가 여러개 있는 경우에는 가장 큰 인덱스를 출력하라. 피보나치 수가 아닌 수가 들어오는 경우는 없다.
* 예시
* 해결 과정
인덱스 0 ~ 100,000 까지의 BigInteger 타입의 배열을 만들고, 해당 배열의 각 인덱스 값들을 DP 알고리즘을 이용해 만들어진 피보나치 수열 값으로 저장한다.
이후 각 테스트 케이스마다 입력된 값을 UpperBound(중복이 존재하는 배열에서 특정값이 존재하는 마지막 인덱스 찾기) 방식의 이분탐색을 활용하여 해당 값이 저장된 인덱스를 찾아주었다.
* 코드
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.math.BigInteger;
public class Main {
public static void main(String[] args) throws NumberFormatException, IOException {
new Main().solution();
}
static BigInteger[] fibonacci = new BigInteger[100001];
private void solution() throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int tc = Integer.parseInt(br.readLine());
fibonacci[0] = new BigInteger("0");
fibonacci[1] = new BigInteger("1");
for (int i = 2; i < fibonacci.length; i++) {
fibonacci[i] = fibonacci[i - 1].add(fibonacci[i - 2]);
}
for (int i = 0; i < tc; i++) {
BigInteger fn = new BigInteger(br.readLine());
int index = upperBound(fn);
bw.write(index + "\n");
}
bw.flush();
bw.close();
br.close();
}
private int upperBound(BigInteger fn) {
int start = 0;
int end = fibonacci.length;
while (start < end) {
int mid = (start + end) / 2;
if (fn.compareTo(fibonacci[mid]) == 0 || fn.compareTo(fibonacci[mid]) == 1) {
start = mid + 1;
} else {
end = mid;
}
}
return start - 1;
}
}
조금 무식하지만 문제에서 조건으로 제시된 100,000 크기만큼의 피보나치 수열을 만들어서 배열에 저장한 다음, 해당 배열을 대상으로 mid 인덱스에 해당하는 값이 찾고자 하는 값 보다 작은지, 또는 크거나 같은지에 따라 범위를 줄여가며 답을 찾았으므로 이분탐색 문제에 해당된다.
'코딩 테스트 > 이분탐색' 카테고리의 다른 글
백준 26152 - 플래피 버드 스코어링 (0) | 2023.07.07 |
---|---|
백준 14575 - 뒤풀이 (자바 - 이분탐색) (0) | 2023.07.06 |
백준 2792 - 보석 상자 (0) | 2023.07.02 |
백준 2343 - 기타 레슨 (자바 - 이분탐색) (0) | 2023.06.30 |
백준 27932 - 어깨동무 (자바 - 이분탐색) (0) | 2023.06.29 |