2020-05-19 17:31:52 +00:00
|
|
|
#!/usr/bin/env python3
|
2018-10-19 07:58:21 +00:00
|
|
|
|
2017-10-12 19:35:23 +00:00
|
|
|
"""
|
|
|
|
This program calculates the nth Fibonacci number in O(log(n)).
|
2020-05-19 17:31:52 +00:00
|
|
|
It's possible to calculate F(1_000_000) in less than a second.
|
2017-10-12 19:35:23 +00:00
|
|
|
"""
|
2024-03-13 06:52:41 +00:00
|
|
|
|
2020-09-23 11:30:13 +00:00
|
|
|
from __future__ import annotations
|
|
|
|
|
2017-10-12 19:35:23 +00:00
|
|
|
import sys
|
|
|
|
|
|
|
|
|
2020-05-19 17:31:52 +00:00
|
|
|
def fibonacci(n: int) -> int:
|
|
|
|
"""
|
|
|
|
return F(n)
|
|
|
|
>>> [fibonacci(i) for i in range(13)]
|
|
|
|
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]
|
|
|
|
"""
|
2017-10-12 19:35:23 +00:00
|
|
|
if n < 0:
|
|
|
|
raise ValueError("Negative arguments are not supported")
|
|
|
|
return _fib(n)[0]
|
|
|
|
|
|
|
|
|
|
|
|
# returns (F(n), F(n-1))
|
2020-09-23 11:30:13 +00:00
|
|
|
def _fib(n: int) -> tuple[int, int]:
|
2020-05-19 17:31:52 +00:00
|
|
|
if n == 0: # (F(0), F(1))
|
2017-10-12 19:35:23 +00:00
|
|
|
return (0, 1)
|
2020-05-19 17:31:52 +00:00
|
|
|
|
2024-04-22 19:56:14 +00:00
|
|
|
# F(2n) = F(n)[2F(n+1) - F(n)]
|
2020-05-19 17:31:52 +00:00
|
|
|
# F(2n+1) = F(n+1)^2+F(n)^2
|
|
|
|
a, b = _fib(n // 2)
|
|
|
|
c = a * (b * 2 - a)
|
|
|
|
d = a * a + b * b
|
|
|
|
return (d, c + d) if n % 2 else (c, d)
|
2017-10-12 19:35:23 +00:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2020-05-19 17:31:52 +00:00
|
|
|
n = int(sys.argv[1])
|
|
|
|
print(f"fibonacci({n}) is {fibonacci(n)}")
|