https://www.acmicpc.net/problem/11444
11444번: 피보나치 수 6
첫째 줄에 n이 주어진다. n은 1,000,000,000,000,000,000보다 작거나 같은 자연수이다.
www.acmicpc.net
걸린 시간 : 36분 32초
재밌을 것 같아서 도전! 했는데,,
숫자가 너무 크다. 이러면 무조건 O(logN) 알고리즘을 써야 하고, 그렇단 말은 F(2n) 과 F(n) 과의 관계를 알아내면 끝이다.
...
...
도대체 무슨 관계가 있는지 전혀 감도 안 오고 배운 적도 없는 것 같다..
이런 너무 수학적인 주제를 공부할 시간에 코딩 공부를 좀 더 하자는 핑계 생각에 잠깐 검색을 해보았더니 이런 식이 나온다.

이걸 제가 어떻게 알아요
이 식의 m에 n, n+1 을 대입해 정리하면 이렇게 나온다.
- F(2n) = F(n) ( 2F(n-1) + F(n) )
- F(2n+1) = (F(n))^2 + (F(n+1))^2
이 수식과 함께 다이나믹 프로그래밍으로 저장해서 재호출을 막도록 하자.
또한, 그냥 배열에 넣으면 당연히 저장공간이 터지기 때문에 HashMap 을 사용하자.
정답 코드
import java.util.HashMap; import java.util.Map; import java.util.Scanner; public class BOJ11444 { static Map<Long, Long> map = new HashMap<>(); static long n; public static void main(String[] args) { Scanner sc = new Scanner(System.in); n = sc.nextLong(); System.out.println(fib(n)); } static long fib(long k) { if (map.containsKey(k)) { return map.get(k); } if (k == 0) return 0; if (k == 1) return 1; if (k % 2 == 1) { long ans = (fib(k/2) * fib(k/2) + fib(k/2+1) * fib(k/2+1)) % 1000000007; memo(k, ans); return ans; } long ans = (fib(k/2) * (2*(fib(k/2-1)) + fib(k/2))) % 1000000007; memo(k, ans); return ans; } static void memo(long k, long ans) { if (map.containsKey(ans)) return; map.put(k, ans); } }
'Baekjoon Online Judge' 카테고리의 다른 글
[BOJ] 2630 : 색종이 만들기 (Java) with 분할 정복 (1) | 2023.11.09 |
---|---|
[BOJ] 1927 : 최소 힙 (Java) (0) | 2023.11.02 |
[BOJ] 9251 : LCS (Java) (0) | 2023.11.02 |
[BOJ] 1987 : 알파벳 (Java) (1) | 2023.10.26 |
[BOJ] 1744 : 수 묶기 (Java) (1) | 2023.10.26 |