Введение

Модель вычисления

Имеется вычислительная машина, на которой отрабатывают алгоритмы

Вычисление чисел Фиббоначи

Числа Фиббоначи определяются следующим образом:

$F_0 = 0$ $F_1 = 1$ $F_n = F_{n-1}+F_{n-2}$

Утверждение: $F_n <= 2^n.$

По индукции: $F_n = F_{n-1}+F_{n-2}<=2^{n-1}+2^{n-2}<=2^n$

Утверждение: $F_n \geqslant 2^{n/2}$, начиная с $n=6.$

$F_n = F_{n-1}+F_{n-2} \geqslant 2^{(n-1)/2} + 2^{(n-2)/2} > 2^{n/2}$

Утверждение: Существует $\exists a$: $F_n = a^n$

$a^n = a^{n-1}+a^{n-2}$ $a^2-a-1=0$ $a=\frac{1+\sqrt{2}}{2} = \varphi = 1\sigma$

def fib1(n):
  if n < 2:
    return n
  return fib1(n-1) + fib1(n-2)

Утверждение: Количество вызовов $fib1$ при вычислении функции $fib1(n)$ больше чем $Fib(n) \Rightarrow$ экспоненциальное число вызовов.

Доказательство. $T(f_1(n)) = T(f_1(n-1)) + T(f_1(n-2)) + 1$ — кол-во вызовов $fib1$ в вызове $fib1(n).$

$T(f_1(0)) = T(f_1(1)) = 1$ $T(f_1(n)) \geqslant Fib(n) \geqslant 1\sigma^n$

def fib2(n):
  a = [0, 1]  # 0-n операций (зависит от машины)
  for i in range(2, n + 1):
    a.append(a[i-1] + a[i-2])  # n операций
  return a[n]

Итого порядка $2n$ операций и $n$ памяти

def fib3(n):
  if n == 0:
    return 0
  a, b = 0, 1
  for _ in range(2, n + 1):
    a, b = b, a + b  # 3 операции
  return b

Итого $3n$ оперций, константая память.

Если потребуется вычислять большие числа, то они довольно быстро вылезут за пределы машинного слова (в $F_n \simeq n$ цифр), соотвественно сложение из константного станет линейным, а алгоритм — квадратичным.

$\left(\begin{array}{cc}1 & 1 \\ 1 & 0\end{array}\right)^n$

В $(1, 0)$ и $(0, 1)$ ячейках будет $n$-ое число, скорость работы логарифмическая.

Ресурсы

Ресуры, интересующие нас при построении алгоритма:

Оценки сложности

Всякие утверждения: 1. $n^k = O(n^l), l \geqslant k$ 2. $\log^kn = O(\log^ln), l\geqslant k$ 3. $a^n = O(c^n), c \geqslant a \geqslant 1$

Соотношения: 1. $\log^kn = O(n^l)$ 2. $n^k = O(a^n)$ 3. $n\log_2n = \Theta(n\log_3n)$ 4. $2^{n\log_2n} = n^n$ $2^{n\log_3n} = n^{n \log_32}$ $2^{n\log_2n} = \Omega(2^{n\log_3n})$