일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 데이터엔지니어
- 윈도우클린설치
- IDA*
- 알고리즘특강
- 실전sql퀵스타트
- 우분투22.04
- 비트집합
- code golf
- Short Coding
- 현대자동차
- 소프티어부트캠프
- hmg소프티어부트캠프
- spaghetti code
- 백준
- 소프티어
- 표준입력
- 파이썬
- 현대자동차그룹
- ucpc
- open(0)
- boj
- 피보나치수
- 데이터엔지니어링
- Python
- 대학생알고리즘특강
- 그리디알고리즘
- zshrc
- 도커
- docker
- 에라토스테네스의채
- Today
- Total
Neo Ground
[백준 | Python] #11444 - 피보나치 수 (cache decorator) 본문
문제
$n$번 째 피보나치 수를 $10^9+7$로 나눈 나머지를 구하여라. $n$은 $10^{18}$보다 작거나 같은 자연수이다.
아이디어
$n$이 매우 크다. 단순하게 기본적인 피보나치 재귀 함수를 구현해서는 불가능하다.
따라서 다음과 같이 생각해 보았다.
1. 일반항을 통해 구하기 -> 일반항에 $\sqrt 5$가 포함되어 계산이 간단하지 않다. 점화식에 포함된 제곱을 분할정복을 사용한다 하더라도 많은 제곱을 할 수록 부동소수점의 오차가 쌓일 것이다. -> 불가능
2. 점화식을 통한 분할정복을 통해 구하기 -> $f(2n)=g(f(n), f(n+1))$와 유사한 형태의 점화식이 존재할 것이다. (아마?) 이를 이용해 상대적으로 짧은 시간에 문제를 해결할 수 있을 것이다.
구현
점화식을 구하기 귀찮았다. 대충 이 문제를 구글링 하니 바로 찾을 수 있었다.
$f(2n) = f(n)\times(2f(n-1) + f(n))$
$f(2n+1) = f(n+1)^2 + f(n)^2$
참고: BOJ - 11444 피보나치 수 6 해결 전략 (C++) (velog.io)
이를 통해 재귀함수만 구현하면 된다.
다만 아무 생각 없이 재귀만 구현하면 재귀 시에 무수히 많은 가지가 펼쳐지며 엄청난 개수의 $f(1)$ 내지 $f(2)$를 계산하게 될 것이다.
따라서 피보나치 수를 어느 정도 저장하며 재귀를 구현해야 한다.
이때 피보나치 수를 저장하는 딕셔너리나 리스트를 만들어둘 수도 있겠지만 나는 파이썬에서 기본적으로 제공하는 cache decorator를 사용하였다.
decorator란, def
구문 위에 @어쩌고
가 달린 것을 말한다.
대충 함수에 자동적으로 특별한 기능을 추가해 준다고 생각하면 된다.
@cache
는 functools
모듈을 불러와 사용할 수 있으며 이를 사용하면 해당 함수는 동일한 인자값에 대한 리턴값을 캐시에 저장하게 된다.
다시 말해, 딕셔너리나 리스트를 만들 필요 없이 알아서 함수의 리턴값을 기억해 계산량을 줄여준다는 것이다.
결과적으로 decorator를 통해 import 구문을 포함하여 단 두 줄만으로 귀찮은 메모리 구현 없이 문제를 해결할 수 있다.
코드
from functools import cache
MOD = 1_000_000_007
@cache
def fib(n):
if n <= 2:
return 1
elif n % 2 == 0:
return (fib(n//2) * (2*fib(n//2-1) + fib(n//2))) % MOD
else:
return (fib(n//2+1)**2 + fib(n//2)**2) % MOD
print(fib(int(input())))
후기
데코레이터에 대해 알게 되고 백준에서도 한번쯤 사용해 보고 싶었는데 드디어 제대로 사용해 보았다.
'Problem Solving' 카테고리의 다른 글
[백준 | Python] #23731 - XOR-ABC (1) | 2023.12.27 |
---|---|
[백준] #18789 - 814 - 2 (1) | 2023.12.18 |
[백준 | Python] #2549 - 루빅의 사각형 (IDA* 알고리즘) (0) | 2023.08.28 |
백준 파이썬 숏코딩 팁 (Python Code Golf) (0) | 2023.08.26 |
[백준 | Python] #11967 - 불켜기 (0) | 2023.07.26 |