====== Fibonacci Representation ======
===== 풀이 =====
* 그리디하게, 만들려는 수에 가장 근접한 피보나치 수를 찾아서 포함시키는 방식으로 반복하면 찾을 수 있다.
* f(n) 이하의 피보나치 수들만을 더해서 만들어진 수가 f(n+1)이상이라면, 이것을 f(n+1)을 포함하는 피보나치수의 합으로 바꿔 쓰는 것이 항상 가능하고, 이 경우에 더해지는 피보나치수의 갯수가 증가하지는 않는다.
* [[ps:피보나치 수#Zeckendorf's_theorem]]도 참고하자.
* 만들려는 수에 가장 근접한 피보나치 수를 찾는 것은 몇가지 방법이 있는데.. 만들려는수가 x이고, %%F(m) <= n < F(m+1)%%인 F(m)과 F(m+1)을 구하는거라고 하자. 그러면 m은 O(logn)이다.
* 그냥 전처리 없이 F(1),F(2),... 를 계속 만들어가면서 찾는다면 O(m)
* F(i)을 모두 전처리해서 O(m)에 미리 구해놓고서, 이분탐색으로 찾는다면 O(logm)
* 피보나치 수의 일반식 $F_{n}=\left\lfloor {\frac {\varphi ^{n}}{\sqrt {5}}}+{\frac {1}{2}}\right\rfloor$ 을 역으로 써서 $n(F)=\left\lceil \log _{\varphi }\left(F\cdot {\sqrt {5}}-{\frac {1}{2}}\right)\right\rceil $으로 계산하는 방법
* O(1)에 m을 구할수 있고.. F(i)을 모두 전처리해서 미리 구해놨다면 F(m)을 구하는 것까지도 O(1)이겠지만.. 계산도 복잡하고 실수오차도 있을거 같은 느낌..
* 결국은 m자체가 별로 크지 않으니까 (n<=4*10^17 문제조건에서 m은 100 이하이다) 가장 간단한 첫번째 방법으로 구현했다. 이 방식으로 m 개의 항을 구해도 O(m^2) = O(log^2(n))이다
* O(m^2)으로 풀고 나서, 다른 사람 답안을 보다가 훨씬 좋은 방법을 알게 되었다. n에 가장 근접한 피보나치 수 F(m)을 찾아서 빼 준다음에, n-F(m)에 가장 근접한 피보나치 수를 찾으려고 할때, 다시 F(0)부터 만들어나가며 찾을 필요가 없다. F(m-1)에서부터 아래로 내려오면서 찾으면 되고, 이런식으로 접근하면 피보나치수들을 다시 한번씩만 만들게 되면 끝나므로, 결국 O(m^2)이 아니라 O(m)에 해결 가능하다.
* 실제 수행시간은 m이 작아서 시간차이는 하나도 안난다.
===== 코드 =====
==== 코드 1 - O(t*log^2(n)) ====
"""Solution code for "BOJ 8229. Fibonacci Representation".
- Problem link: https://www.acmicpc.net/problem/8229
- Solution link: http://www.teferi.net/ps/problems/boj/8229
Tags: [Greedy]
"""
def main():
p = int(input())
for _ in range(p):
k = int(input())
answer = 0
while k:
a, b = 1, 1
while b <= k:
a, b = b, a + b
k = min(b - k, k - a)
answer += 1
print(answer)
if __name__ == '__main__':
main()
==== 코드 2 - O(t*logn) ====
"""Solution code for "BOJ 8229. Fibonacci Representation".
- Problem link: https://www.acmicpc.net/problem/8229
- Solution link: http://www.teferi.net/ps/problems/boj/8229
Tags: [Greedy]
"""
def main():
p = int(input())
for _ in range(p):
k = int(input())
answer = 0
a, b = 1, 1
while b <= k:
a, b = b, a + b
while k:
while a > k:
a, b = b - a, a
k = min(b - k, k - a)
answer += 1
print(answer)
if __name__ == '__main__':
main()
{{tag>BOJ ps:problems:boj:플래티넘_4}}