fft 傅里叶变换最初板

引入洛谷基础题目:https://www.luogu.org/problem/P3803

题目背景

这是一道 FFT 模板题

题目描述

给定一个 nn 次多项式 F(x),和一个 mm 次多项式 G(x)。

请求出 F(x)和 G(x)的卷积。

输入格式

第一行 2 个正整数 n,m。

接下来一行 n+1个数字,从低到高表示 F(x) 的系数。

接下来一行 m+1 个数字,从低到高表示G(x) 的系数。

输出格式

一行 n+m+1 个数字,从低到高表示 F(x)∗G(x) 的系数。

输入: 

1 2
1 2
1 2 1

输出:

1 4 5 2

表示时间不多,不想写太多论述,只是为自己的记录。。

前提:复数 为啥》:复数可以代表角度和模长,复数相乘等于模长相乘角度相加, 所以单位圆内的复数相乘就等于角度相加,所以我们可以选择这些为,基础点来转换点值法,再用互斥复数求系数法(记得有个除n)n一定要是2的次幂000。

struct co {
    double x, y;
    co(){}
    co (double xx, double yy):x(xx),y(yy) {}
    co operator+(const co &a) const {
        return co(x+a.x, y+a.y);
    }
    co operator-(const co &a) const {
        return co(x-a.x, y-a.y);
    }
    co operator*(const co &a) const {
        return co(x*a.x-y*a.y, x*a.y+a.x*y);
    }
} a[mx], b[mx];

void fft(co *a, int n, int type) {
    if (n == 1) return;
    int n1 = n>>1;
    co a1[n1], a2[n1];
    for (int i = 0; i < n1; ++i)
        a1[i] = a[i<<1], a2[i] = a[i<<1|1];
    fft(a1, n1, type);
    fft(a2, n1, type);
    co wn(cos(2.0*pi/n), type*sin(2.0*pi/n)), w(1, 0);
    for (int i = 0; i < n1; ++i, w = w*wn) {
        co t = w*a2[i];
        a[i] = a1[i]+t, a[i+n1] = a1[i]-t;
    }
    return;
}
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while (c < '0' || c > '9') {if (c == '-')f = -1; c = getchar();}
    while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
    return x * f;
}
int main() {
    int n, m, as = 1;
    n = read(), m = read();
    while (as<=n+m) as<<=1;
    for (int i = 0; i <= n; ++i) a[i].x = read();
    for (int i = 0; i <= m; ++i) b[i].x = read();
    fft(a, as, 1); fft(b, as, 1);
    for (int i = 0; i <= as; ++i)
        a[i] = a[i]*b[i];
    fft(a, as, -1);
    for (int i = 0; i <= n+m; ++i)
        printf("%d ", (int)(a[i].x/as+0.5));
}

 

你可能感兴趣的:(fft,------数论------,fft)