Featured image of post Производящие функции: В чем польза превращения последовательности в функцию?

Производящие функции: В чем польза превращения последовательности в функцию?

Введение в то, как вычислять комбинации оплаты монетами и перестановки в качестве коэффициентов уравнения. Объяснение магии производящих функций, включая их применение к последовательности Фибоначчи.

В мире математики существуют концепции, которые действуют как «магические мосты», соединяя на первый взгляд не связанные между собой области. Одной из них является производящая функция (Generating Function). Путем преобразования дискретной «последовательности» в непрерывную «функцию» сложные комбинаторные задачи можно свести к алгебраическим вычислениям.

В этой статье мы начнем с базовой идеи производящих функций и подробно объясним их удивительную мощь — от вычисления комбинаций оплаты монетами до вывода общего члена последовательности Фибоначчи. Кроме того, мы затронем их применение к формальным степенным рядам (FPS) в алгоритмах и спортивном программировании.

1. Что такое производящая функция?

Пусть задана последовательность $a_0, a_1, a_2, \dots$. Рассмотрим функцию $A(x)$, в которой каждый член является коэффициентом при соответствующей степени $x$.

$$ A(x) = a_0 + a_1 x + a_2 x^2 + a_3 x^3 + \dots = \sum_{n=0}^{\infty} a_n x^n $$

Эта функция $A(x)$ называется обыкновенной производящей функцией (Ordinary Generating Function) для последовательности $\{a_n\}$.

Зачем выполнять такое преобразование? Потому что операции над последовательностями можно заменить алгебраическими операциями над функциями. Такие операции, как сдвиг, сложение или свертка последовательностей, преобразуются в знакомые операции, такие как сложение, умножение, дифференцирование и интегрирование функций.

  graph LR
    A["Последовательность (Дискретная)"] -->|"Преобразование в производящую функцию"| B["Функция (Непрерывная)"]
    B -->|"Алгебраические операции (Производная, Произведение)"| C["Новая функция"]
    C -->|"Извлечение коэффициентов"| D["Новая последовательность"]
    A -.->|"Сложные операции"| D

2. Комбинации оплаты монетами и производящие функции

Чтобы интуитивно понять силу производящих функций, давайте рассмотрим задачу «оплаты монетами».

Задача: Найдите количество комбинаций $a_n$ для оплаты ровно $n$ иен с использованием монет достоинством 1 иена, 2 иены и 5 иен.

Мы решаем эту задачу с помощью производящих функций. Для каждой монеты мы создаем многочлен, соответствующий количеству используемых монет.

  • Выбор монет по 1 иене: $1 + x + x^2 + x^3 + \dots$ (0 монет, 1 монета, 2 монеты, …)
  • Выбор монет по 2 иены: $1 + x^2 + x^4 + x^6 + \dots$
  • Выбор монет по 5 иен: $1 + x^5 + x^{10} + x^{15} + \dots$

Рассмотрим функцию $f(x)$, полученную путем их перемножения.

$$ f(x) = (1 + x + x^2 + \dots)(1 + x^2 + x^4 + \dots)(1 + x^5 + x^{10} + \dots) $$

Коэффициент при $x^n$ при раскрытии скобок в этом уравнении будет в точности равен количеству комбинаций $a_n$ для оплаты $n$ иен. Используя формулу суммы бесконечной геометрической прогрессии $1 + r + r^2 + \dots = \frac{1}{1-r}$, функцию $f(x)$ можно кратко выразить в виде рациональной функции:

$$ f(x) = \frac{1}{1-x} \cdot \frac{1}{1-x^2} \cdot \frac{1}{1-x^5} $$

Другими словами, не используя сложные рекуррентные соотношения или циклические вычисления, вы можете найти количество комбинаций для любого $n$, просто найдя коэффициенты разложения Тейлора этой функции. В программировании эта концепция является важной основой для динамического программирования (DP).

Свертка и умножение многочленов

Почему произведение функций соответствует подсчету комбинаций? Давайте посмотрим, что происходит, когда мы перемножаем производящие функции $A(x), B(x)$ двух последовательностей $a_n$ и $b_n$.

$$ A(x)B(x) = (a_0 + a_1 x + a_2 x^2 + \dots)(b_0 + b_1 x + b_2 x^2 + \dots) $$

Коэффициент при $x^n$ при раскрытии скобок будет $\sum_{k=0}^{n} a_k b_{n-k}$. Это называется сверткой (Convolution). В примере с монетами сложение комбинаций вроде «набрать $k$ иен монетами по 1 иене и $n-k$ иен монетами по 2 иены» автоматически вычисляется с помощью этого произведения функций.

3. Применение к последовательности Фибоначчи

Далее, в качестве более продвинутого применения, давайте найдем общий член последовательности Фибоначчи. Последовательность Фибоначчи $F_n$ определяется следующим образом:

  • $F_0 = 0$
  • $F_1 = 1$
  • $F_n = F_{n-1} + F_{n-2} \quad (n \ge 2)$

Пусть производящая функция этой последовательности равна $F(x) = \sum_{n=0}^{\infty} F_n x^n$.

$$ \begin{aligned} F(x) &= F_0 + F_1 x + \sum_{n=2}^{\infty} F_n x^n \\ &= 0 + x + \sum_{n=2}^{\infty} (F_{n-1} + F_{n-2}) x^n \\ &= x + x \sum_{n=2}^{\infty} F_{n-1} x^{n-1} + x^2 \sum_{n=2}^{\infty} F_{n-2} x^{n-2} \\ &= x + x \sum_{m=1}^{\infty} F_m x^m + x^2 \sum_{k=0}^{\infty} F_k x^k \end{aligned} $$

Здесь, поскольку $F_0 = 0$, то $\sum_{m=1}^{\infty} F_m x^m = F(x)$. Следовательно,

$$ F(x) = x + x F(x) + x^2 F(x) $$

Решение этого уравнения относительно $F(x)$ дает производящую функцию для последовательности Фибоначчи.

$$ F(x) = \frac{x}{1 - x - x^2} $$

Удивительно, но информация о бесконечно продолжающейся последовательности Фибоначчи была сжата в одну простую дробную функцию.

Разложение на простейшие дроби и общий член

Чтобы извлечь общий член последовательности из этого выражения, мы раскладываем знаменатель на множители и выполняем разложение на простейшие дроби. Рассматривая решения уравнения $1 - x - x^2 = 0$, пусть $\alpha = \frac{1 + \sqrt{5}}{2}$ (золотое сечение) и $\beta = \frac{1 - \sqrt{5}}{2}$. Знаменатель можно разложить на множители как $(1 - \alpha x)(1 - \beta x)$.

$$ F(x) = \frac{1}{\sqrt{5}} \left( \frac{1}{1 - \alpha x} - \frac{1}{1 - \beta x} \right) $$

Снова применяя формулу суммы геометрической прогрессии в обратную сторону, мы раскладываем каждое слагаемое в степенной ряд.

$$ \frac{1}{1 - \alpha x} = \sum_{n=0}^{\infty} \alpha^n x^n, \quad \frac{1}{1 - \beta x} = \sum_{n=0}^{\infty} \beta^n x^n $$

Подстановка этих выражений и сравнение коэффициентов при $x^n$ приводит к знаменитой формуле Бине.

$$ F_n = \frac{1}{\sqrt{5}} \left( \left( \frac{1 + \sqrt{5}}{2} \right)^n - \left( \frac{1 - \sqrt{5}}{2} \right)^n \right) $$
  graph TD
    S["Рекуррентное соотношение Фибоначчи"] -->|"Определить производящую функцию F(x)"| EQ["Составить уравнение для функции"]
    EQ -->|"Решить алгебраически"| GF["F(x) = x / (1 - x - x^2)"]
    GF -->|"Разложение на простейшие дроби"| PF["(A / (1 - αx)) + (B / (1 - βx))"]
    PF -->|"Разложение в степенной ряд и сравнение коэффициентов"| AN["Общий член (Формула Бине)"]

4. Экспоненциальные производящие функции и перестановки

При работе с комбинаторными задачами, в которых учитывается порядок, то есть с «перестановками», в игру вступает экспоненциальная производящая функция (Exponential Generating Function).

Для последовательности $a_n$ экспоненциальная производящая функция $E(x)$ определяется следующим образом:

$$ E(x) = \sum_{n=0}^{\infty} \frac{a_n}{n!} x^n = a_0 + a_1 x + \frac{a_2}{2!} x^2 + \frac{a_3}{3!} x^3 + \dots $$

При делении на $n!$ вычисления с учетом порядка (такие как дифференцирование) принимают очень аккуратную форму. Например, экспоненциальная производящая функция для последовательности $1, 1, 1, \dots$, в которой все элементы равны $1$, равна $e^x$.

$$ e^x = 1 + x + \frac{x^2}{2!} + \frac{x^3}{3!} + \dots $$

Используя это свойство, количество способов упорядочить элементы или количество перестановок, удовлетворяющих нескольким условиям, можно выразить как произведение экспоненциальных функций.

5. Эволюция к формальным степенным рядам (FPS)

В современной информатике и спортивном программировании производящие функции реализуются как формальные степенные ряды (Formal Power Series, FPS). В FPS нас не волнует, будет ли сходиться результат при подстановке конкретного числового значения вместо $x$ (аналитические свойства); основное внимание уделяется просто алгебраическому манипулированию «последовательностью коэффициентов» как многочленами.

С использованием быстрого преобразования Фурье (БПФ - FFT) или теоретико-числового преобразования (NTT) произведение двух многочленов степени $N$ (т. е. свертку последовательностей длины $N$) можно найти с вычислительной сложностью $\mathcal{O}(N \log N)$. Это позволяет значительно ускорить вычисления, для которых при использовании динамического программирования потребовалось бы время $\mathcal{O}(N^2)$.

6. Заключение

Производящая функция — это не просто «коробка для хранения последовательности». Это «переводчик», который преобразует закономерности и свойства последовательности в функциональную форму, что позволяет применять мощные математические инструменты, такие как математический анализ и алгебра.

  • Подсчет комбинаций заменяется произведением функций.
  • Решение рекуррентного соотношения заменяется решением уравнения и разложением в ряд Тейлора.

Эта идея играет активную роль в самых разных областях: от разработки алгоритмов до сложнейших задач чистой математики. Обязательно добавьте этот новый взгляд на последовательности как на «функции» в свой набор инструментов для мышления.

comments powered by Disqus