首先是FFT:
FFT是将系数表达的多项式转化为点值表达的多项式的一类变换:
我们希望计算:
\(A(x) = \sum_{j=0}^{n-1}a_{j}x^{j}\)
对于n个单位复数根有:
\(y_{k} = A(\omega _{n}^{k}) = \sum_{j = 0}^{n - 1}a_{j}\omega _{n}^{kj}\)
我们定义
\(A^{[0]}(x)= a_{0} + a_{2}x+a_{4}x^{2}+ \cdot \cdot \cdot +a_{n-2}x^{n/2-1}\)
\(A^{[1]}(x)= a_{1} + a_{3}x+a_{5}x^{2}+ \cdot \cdot \cdot +a_{n-1}x^{n/2-1}\)
即\(A^{[0]}\)包含所有偶数下标的系数,\(A^{[1]}\)包含所有奇数下标的系数
容易得到
\(A(x)=A^{[0]}(x^{2})+xA^{[1]}(x^{2})\)
所以问题就转化为了两个更小规模的问题:
求次数为n / 2的多项式\(A^{[0]}\)和\(A^{[1]}\)在点
\((\omega _{n}^{0})^{2},(\omega _{n}^{1})^{2},\cdot \cdot \cdot ,(\omega _{n}^{n-1})^{2}\)
的取值
以下是代码
struct cpy { double i, j; }a[N], b[N], c[N]; cpy operator+ (cpy a, cpy b) {return (cpy){a.i + b.i, a.j + b.j};} cpy operator- (cpy a, cpy b) {return (cpy){a.i - b.i, a.j - b.j};} cpy operator* (cpy a, cpy b) {return (cpy){a.i * b.i - a.j * b.j, a.i * b.j + a.j * b.i};} const double pi = acos(-1); void FFT(cpy a[], int n, int fl = 1) { for (int i = 1, j = (n >> 1); i < n; ++ i) { if (i < j) swap(a[i], a[j]); int k; for (k = (n >> 1); j & k; j ^= k, k >>= 1); j ^= k; } for (int i = 2; i <= n; i = i << 1) { cpy w = (cpy){cos(fl * 2 * pi / i), sin(fl * 2 * pi / i)}; for (int j = 0; j < n; j += i) { cpy wn = (cpy){1, 0}; for (int k = j; k < j + i / 2; ++ k) { cpy u = a[k], v = a[k + i / 2] * wn; a[k] = u + v; a[k + i / 2] = u - v; wn = wn * w; } } } if (fl < 0) for (int i = 0; i < n; ++ i) a[i].i /= n; }
FFT
然后是NTT:
时间: 2024-11-03 05:43:11