Лекция 16

Вычисление дискретного преобразования Фурье и время работы алгоритма Шёнхаге-Штрассена

(Конспект: М. Кузнецов)

16.1 Анализ алгоритма Шёнхаге-Штрассена

Хочется оценить время работы алгоритма. Лемма 16.1. ДПФ можно вычислить за время O(bl log b).

Мы докажем эту лемму во второй части лекции.

Итак, рекуррентное соотношение на время работы алгоритма Шёнхаге-Штрассена: T (n) ⩽ bT (2l) (рекурсивные вызовы) +

O(bl log b) (время на ДПФ) +

дешевые операции (сложение, битовые сдвиги) + O((3b log b)^{log_{2} 3}) (это время работы �простого� алгоритма,

но оно спрячется в O(bl log b)).

Итого,

T (n) ⩽ bT (2l) + cbl log b = bT (2l) + cn log n. Положим T′(n) = T (n)/n. Тогда

T′(n) ⩽ 2T′(4\sqrt{n}) + c log n. Докажем, что T′(n) = O(log n log log n) (т.е. T (n) = O(n log n log log n) — почти линейное время).

Доказываем по индукции; пусть для маленьких n выполняется T′(n) ⩽ c′ log n log log n. Индукционный переход происходит от 4\sqrt{n} к n:

T′(n) ⩽ 2c′(2 + log n/2) log(2 + log n/2) + c log n ⩽

c log n+4c′ log(2/3)+4c′ log log n+c′ log(2/3) log n+c′ log n log log n.

За счет увеличения c′ по сравнению с c можно добиться, чтобы слагаемое c′ log(2/3) log n (отрицательное) стало по абсолютной величине больше, чем три первые (положительные) слагаемые; а оставшееся слагаемое — это то, чем мы оцениваем.

16.2 Вычисление ДПФ

Научимся вычислять ДПФ (вычисление обратного преобразования производится аналогично — упражнение). Нам нужно вычислять некоторый многочлен p(x) во многих точках вида w^{k}, где w — степень двойки (именно, 2^{4l/b}), а вычисление ведется по модулю 2^{2l} + 1.

Для того, чтобы вычислить значение в точке x_{0}, достаточно поделить на x − x_{0} с остатком:

p(x) = q(x)(x − x_{0}) + r(x), r(x) = const (это и есть p(x_{0}).

Пусть p(x) = a_{0} + a_{1}x + … + a_{n−1}x^{n−1}. Тогда

(F (a))_{i} = ∑_{j=0}^{n−1}(w^{i})^{j}a_{j} = p(w^{i}).

Значит, надо рассмотреть p mod (x − w^{i}).

Заметим, что если r = p mod q и q′|q, то pmod q′ = rmod q′. Поэтому остатки mod x − w^{i} можно вычислять так: сначала вычислить остатки mod произведений таких x−w^{i} для разных i, потом остатки этих остатков mod меньших произведений, и т. д.:

n-1 i p mod П( x-w ) i=0 /\ / \ i i

p mod П( x-w ) p mod П( x-w )

(одна половина возможных i) (другая половина)

/ \ / \ / \ / \ .....................

i j

p mod (( x-w )( x-w )) (конкретные пары)

/\ /\ /\ /\ /\ /\ /\ /\ /\

i j

... p mod ( x-w ) p mod ( x-w )

Будем разбивать не на i ⩽ n/2, i > n/2, а аккуратно: так, чтобы произведения получались красивыми.

Лемма 16.2 (к лемме 16.1). Можно сгруппировать так, чтобы все произведения ∏(x − w^{i}) в дереве имели вид x^{t} − w^{s}.

Задача 16.1. Доказать лемму 16.1.

Указание. Пусть n = 2^{k}. Определим rev(j) = d_{k−1} … d_{0}, где d_{0} … d_{k−1} — битовое представление числа j. Тогда можно доказать, что

∏_{j=l}^{l+2^{m}−1}(x − w^{rev(j)}) = x^{2^{m}} − w^{rev(l/2^{m})}.

(Здесь m — номер уровня в дереве.)

Итак, какие же вычисления надо производить?

∑_{i=0}^{2t−1} a_{i}x^{i} mod (x^{t} − w^{s}) = ∑_{j=0}^{t−1}(a_{j} + w^{s}a_{j+t})x^{j}

(первая часть, 0 ⩽ j ⩽ t − 1, — без изменений, а во второй вместо x^{t} заменили на w^{s}). Все, что здесь надо делать — сложение и умножение на степень двойки.

Теперь можно доказать и лемму 16.1, подсчитав количество операций, выполняемых в этом дереве: на каждом уровне дерева — O(b) операций, каждая из которых занимает время O(l); количество уровней — log b.