Фурье
- Чтобы перемножить многочлены: A, B → F(A), F(B) → F(C)=F(A)*F(B) → C
- Нужно научиться интерполировать и экстерполировать. Научимся считать значение в точках k=0..n-1, z[k]=(cos(2πk/n), sin(2πk/n))
- Решаем рекурсивно т.к. любой многочлен P(x) можно разбить на четные и нечетные степени: P(x) = A(x2) + x*B(x2).
- Получили алгоритм прямого преобразования (экстерполяции) за O(NlogN). A --> FFT(A)
- Обратное преобразование в теории. Есть система уравнений и факт, что z[0]k+z[1]k+...+z[n-1]k == 0, если k = 1..N-1. Решаем систему.
- Обратное преобразование на практике: B := FFT(A). C := FFT(B). D := C.reverse(2,N). E := D/N. Утверждается, что A == E.
Оптимизации - нужно рассказывать, уже после того, как человек закодил Фурье.
- Сделаем мало умножений (в 2 раза меньше, т.к. wn/2 = -1).
- Раздвоение (2 прямых в одном).
- Нерекурсивная реализация (рекурсия = спуск за O(NlogN) + подъем за O(NlogN), оставим только подъем).
- Нерекурсивная реализация. Реверс битов. Rev[a] = Rev[a / 2] / 2 + ((a & 1) << (N - 1))
- Еще лучше так: 0.5 * (Рекурсия + Нерекурсивная реализация)
- Зацикливание массива в задаче 110304a1 : 3A (т.к. длина всегда ровно 2n).
Практика
- Напишите Фурье. 110304a1 : 3L
- Решите хоть одну задачку с помощью Фурье. 110304a1 : 3K
- Напишите Раздвоение. 110304a1 : 3H
- Напишите Фурье по простому модулю. 110304a1 : 3F
- Решите и соптимизьте. 110304a1 : 3A
- Решите и соптимизьте. 110304a1 : 3D
Код
- Короткая реализация Фурье от
Burunduk1
. [link]