FFT参考文章1
FFT参考文章2
快速傅里叶变换实现将两个多项式的乘法从O(n2)时间复杂度降低到O(nlogn)
主要思想为分治,实现为DFT(离散傅里叶变换)和IDFT(离散傅里叶逆变换),将多项式的系数表达式和点值表达式建立联系
递归实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| #include <stdio.h> #include <string.h> #include <ctype.h> #include <math.h> #include <stdlib.h>
#define max(a, b) a>b?a:b #define MAX 1<<22 #define eps 1e-6 #define pi acos(-1.0) typedef struct complex { double x; double y; } Complex, *Complexprt; Complex a[MAX], b[MAX];
void mulComplex(Complexprt w1, Complexprt w2) { double x = w1->x * w2->x - w1->y * w2->y; double y = w1->x * w2->y + w1->y * w2->x; w1->x = x; w1->y = y; }
void FFT(Complex a[], int n, int inv) { if (n == 1) { return; } int mid = n / 2; Complex A1[mid + 1]; Complex A2[mid + 1]; for (int i = 0; i < n; i += 2) { A1[i / 2] = a[i]; A2[i / 2] = a[i + 1]; } FFT(A1, mid, inv); FFT(A2, mid, inv); Complex w0 = (Complex) { 1, 0 }; Complex wn = (Complex) { cos(2 * pi / n), inv * sin(2 * pi / n) }; for (int i = 0; i < mid; i++, mulComplex(&w0, &wn)) { a[i].x = A1[i].x + w0.x * A2[i].x - w0.y * A2[i].y; a[i].y = A1[i].y + w0.x * A2[i].y + w0.y * A2[i].x; a[i + n / 2].x = A1[i].x - w0.x * A2[i].x + w0.y * A2[i].y; a[i + n / 2].y = A1[i].y - w0.x * A2[i].y - w0.y * A2[i].x; } }
int main() { int n, m; scanf("%d%d", &n, &m); for (int i = 0; i < n; i++) { double x; scanf("%lf", &x); a[i].x = x; } for (int i = 0; i < m; i++) { double x; scanf("%lf", &x); b[i].x = x; } int len = max(1, (int) ceil(log2(n + m))); len = 1 << len; FFT(a, len, 1); FFT(b, len, 1); for (int i = 0; i <= len; i++) { mulComplex(&a[i], &b[i]); } FFT(a, len, -1); for (int i = 0; i < n + m - 1; i++) { printf("%.0f ", a[i].x / len + eps); } return 0; }
|
迭代实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| #define eps 1e-7 #define pi acos(-1.0) typedef long double ld; typedef struct complex { double x; double y; } Complex, *Complexprt; Complex a[4000005], b[4000005]; char A[1000005], B[1000005]; int rev[4000005]; int ans[4000005];
void mulComplex(Complexprt w1, Complexprt w2) { double x = w1->x * w2->x - w1->y * w2->y; double y = w1->x * w2->y + w1->y * w2->x; w1->x = x; w1->y = y; }
void swap(Complex *a, Complex *b) { Complex p = *a; a->x = b->x; a->y = b->y; b->x = p.x; b->y = p.y; }
void FFT(Complex a[], int n, int inv) { for (int i = 0; i < n; i++) { if (i < rev[i])swap(&a[i], &a[rev[i]]); } for (int h = 1; h < n; h <<= 1) {
Complex wn = (Complex) { cos(pi / h), inv * sin(pi / h) }; for (int j = 0; j < n; j += h << 1) { Complex w0 = (Complex) { 1, 0 }; for (int k = j; k < j + h; k++) { Complex x = a[k]; Complex y = (Complex) {w0.x * a[k + h].x - w0.y * a[k + h].y, w0.x * a[k + h].y + w0.y * a[k + h].x}; a[k] = (Complex) {x.x + y.x, x.y + y.y}; a[k + h] = (Complex) {x.x - y.x, x.y - y.y}; mulComplex(&w0, &wn); } } } if (inv == -1) { for (int i = 0; i < n; i++) { a[i].x = a[i].x / n + eps; } } } int main(){ int len = 1; int l = 0; while (len < n + m - 1) { len <<= 1; l++; } for (int i = 0; i < len; i++) { rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (l - 1)); } FFT(a,len,1); FFT(b,len,1); for (int i = 0; i < len; i++) { mulComplex(&a[i], &b[i]); } FFT(a, len, -1); }
|