| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
Tags
- map
- DP
- LCA
- 트라이
- 비트필드를 이용한 dp
- R 그래프
- 강한 연결 요소
- ccw 알고리즘
- Express.js
- localstorage
- Prisma
- 자바스크립트
- 2-SAT
- 게임 서버 아키텍처
- SCC
- PROJECT
- 그래프 탐색
- 최소 공통 조상
- JavaScript
- trie
- Spin Lock
- Behavior Design Pattern
- 이분 탐색
- MongoDB
- 분리 집합
- 비트마스킹
- Binary Lifting
- Strongly Connected Component
- Github
- 벨만-포드
Archives
- Today
- Total
dh_0e
[PS] 피보나치 수 6 / C++ (백준 11444번) 본문
문제를 해결하기 위한 수학 식을 만들고, 분할 정복으로 해결할 수 있는 문제로, 식을 만드는 과정에서 n이 짝수일 때, 홀수일 때로 나누는 방법을 떠올리기 쉽지 않았다.
풀이 과정

- 다음과 같이 d[i]="i번째 피보나치 수"로 식을 세워서 변형해 보면 다음과 같은 규칙을 찾을 수 있다.

- 이를 이분 탐색을 하며, n이 짝수일 때, 홀수일 때로 나누면 다음과 같이 2개의 식이 나온다.

- 이를 분할 정복으로 구현하되 map을 활용하여 한 번 계산한 fib(n)의 값을 저장해준다. 이렇게 한 번 구했던 fib(n) 값을 중복으로 값을 구하는 상황을 없애주게끔 구현해 주면 이분 탐색 시간 복잡도 * map의 시간 복잡도 = $O(logn) * O(logn)$의 시간 복잡도로 풀 수 있다(=$O(logn)$).
#define MOD 1000000007
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
map<ll, ll> m;
ll fib(ll n)
{
if (m.find(n) != m.end())
return m[n];
if (n % 2 == 0) {
ll k = n / 2;
m.insert({ n, ((fib(k) * fib(k + 1)) % MOD + (fib(k - 1) * fib(k)) % MOD) % MOD });
return m[n];
}
else {
ll k = (n - 1) / 2;
m.insert({ n, ((fib(k + 1) * fib(k + 1)) % MOD + (fib(k) * fib(k)) % MOD) % MOD });
return m[n];
}
}
int main()
{
ll n;
scanf("%lld", &n);
m.insert({ 0, 0 });
m.insert({ 1, 1 });
m.insert({ 2, 1 });
printf("%lld\n", fib(n) % MOD);
return 0;
}
MOD만 변경해주면 피보나치 수 3(백준 2749번)도 AC를 받을 수 있다!
'Problem Solving > Baekjoon' 카테고리의 다른 글
| [PS] 아기 상어 / C++ (백준 16236번) (0) | 2026.01.05 |
|---|---|
| [PS] 비숍 / C++ (백준 1799번) (0) | 2026.01.02 |
| [PS] 골목길 / C++ (백준 1738번) (0) | 2025.12.22 |
| [PS] 오민식의 고민 / C++ (백준 1219번) (0) | 2025.12.18 |
| [PS] 타임머신, 웜홀 (벨만-포드 기초) / C++ (백준 11675, 1865번) (0) | 2025.12.17 |