Говорят, что степень многочлена равна , если его наибольший ненулевой коэффициент стоит у .
Многочлены, подобно скалярам, можно складывать, вычитать и умножать, получая другие многочлены. Многочлены также можно делить, но результат не всегда получается многочленом. В этом смысле множество многочленов является кольцом, подобно кольцу остатков по модулю.
#Представление многочленов и чисел
Программно представлять многочлен проще всего через vector
или обычный статический массив, содержащий его коэффициенты по порядку. Помимо непосредственно многочленов, удобно представлять в таком виде и длинные числа, притворившись, что равно или основанию любой другой системы счисления:
При операциях с длинными числами (например, при умножении), можно проводить соответствующую операцию с многочленами, а затем производить каррирование результата: проходить от нижних разрядов получившегося многочлена к верхним и «сдвигать» переполнившиеся разряды:
const int base = 10;
vector<int> normalize(vector<int> a) {
int carry = 0;
for (int &x : a) {
x += carry;
carry = x / base;
x %= base;
}
while (carry > 0) {
a.push_back(carry % base);
carry /= base;
}
return a;
}
vector<int> multiply(vector<int> a, vector<int> b) {
return normalize(poly_multiply(a, b));
}
Из соображений производительности следует выбирать настолько большое основание, насколько вмещается в используемый тип данных (например, или для int
).
#Коэффициенты разложений
Коэффициенты при , получаемые при возведении бинома в -ную степень, называются биномиальными коэффициентами:
Их удобно считать по следующей формуле: В более общем случае определяют полиномиальный коэффициент, равный количеству раз, которое элемент появится при раскрытии скобки :Биномиальные коэффициенты применяются в комбинаторике и в отрыве от многочленов. В задачах по программированию их подсчет часто требуется проводить по модулю, для чего нужно уметь искать обратные к факториалам.
#Умножение многочленов
При умножении двух многочленов степени и получается многочлен степени . Прямая формула для произведения многочленов имеет вид
Её наивный подсчёт требует операций, но далее в этой главе мы разберем несколько более эффективных алгоритмов — самый быстрый из которых работает всего за .
Этот факт позволяет сводить много комбинаторных задач к произведению многочленов и использованию уже известных алгоритмов для его подсчета. Разберем несколько примеров таких задач.
#2-рюкзак
Даны два массива и размера и . Требуется найти число различных возможных сумм .
.
Рассмотрим многочлены и , в которых коэффициент при -той степени равен числу равных элементов в соответствующем массиве.
Рассмотрим произведение . В получившемся многочлене коэффициент при будет равен
что в свою очередь равно количеству способов набрать сумму ровно .
Значит, мы можем перемножить эти два многочлена за и просто подсчитать число ненулевых коэффициентов результата.
#Мульти-рюкзак
Задача «Вор в магазине» является небольшой модификацией предыдущей:
Имеется типов предметов различных целых стоимостей . Требуется найти количество различный сумм стоимостей наборов из ровно предметов (возможно, с повторениями).
Опять же, рассмотрим многочлен, в котором коэффициент при -той степени равен единице, если существует предмет со стоимостью , и нулю в противном случае.
Если , наша задача свелась к предыдущей: нужно домножить многочлен на самого себя и посмотреть на число ненулевых коэффициентов. В общем же случае нам нужно возвести многочлен в степень и также посчитать ненулевые коэффициенты результата.
Если возводить многочлен в -ную степень наивно, то асимптотика такого решения будет : нужно раз перемножать два многочлена, больший из которых имеет длину .
Воспользуемся бинарным возведением в степень: умножение многочленов ведь ассоциативно. В данном случае асимптотика будет не более : нужно раз умножать два многочлена порядка . Но на самом деле, так как на каждой итерации размер многочлена будет увеличиваться в два раза, в асимптотике учтется только последнее (самое большое) умножение, и поэтому в действительности время работы составит .
#Свёртки
Свёрткой (англ. convolution) называется операция применения некоторой «оконной» функции ко всем отрезкам фиксированной длины исходной функции.

В дискретном случае свертке соответствует сумме вида
В ещё более узком смысле, свертка это результат перемножения многочленов:то есть -тый коэффициент результата равен применению какой-то оконной функции, заданной коэффициентами , к коэффициентам . Значит, подобные функции можно быстро считать через матричное умножение.
Например, так можно (неэффективно) искать битовую подстроку в строке : запишем символы как коэффициенты многочлена и символы в обратном порядке как коэффициенты многочлена и перемножим. В позициях многочлена-результата, где коэффициенты равны , строка входит в .
Также с помощью этого трюка можно решать и другие задачи, например выполнять «fuzzy searching»: коэффициенты, равные , соответствуют вхождениям с ровно ошибками.