FFT

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e7 + 10;
const double Pi = acos(-1.0);
struct Complex {
    double x, y;
    Complex (double xx = 0, double yy = 0) {x = xx, y = yy;}
} a[MAXN], b[MAXN];
Complex operator + (Complex a, Complex b) { return Complex(a.x + b.x , a.y + b.y);}
Complex operator - (Complex a, Complex b) { return Complex(a.x - b.x , a.y - b.y);}
Complex operator * (Complex a, Complex b) { return Complex(a.x * b.x - a.y * b.y , a.x * b.y + a.y * b.x);} 
int N, M;
int l, r[MAXN];
int limit = 1;//要把最高次数变成2的次方结果方便运算
void FFT(Complex *A, int type) {
    for (int i = 0; i < limit; i++)
        if (i < r[i]) swap(A[i], A[r[i]]); //求出要迭代的序列,if是因为否则就换两次就换回来了
    for (int mid = 1; mid < limit; mid <<= 1) 
    { //待合并区间的长度的一半
        Complex Wn( cos(Pi / mid) , type * sin(Pi / mid) ); //单位根,mid本来就是区间长度的一半了,所以不需要2Pi/mid了
        for (int R = mid << 1, j = 0; j < limit; j += R) { //R是区间的长度,j表示前已经到哪个位置了
            Complex w(1, 0); //幂
            for (int k = 0; k < mid; k++, w = w * Wn) { //枚举左半部分
                Complex x = A[j + k], y = w * A[j + mid + k]; //蝴蝶效应
                A[j + k] = x + y;
                A[j + mid + k] = x - y;
            }
        }
    }
}
int main() {
    int N,M;
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>N>>M;
    for (int i = 0; i <= N; i++)
        cin>>a[i].x;
    for (int i = 0; i <= M; i++)
        cin>>b[i].x;
    while (limit <= N + M) limit <<= 1, l++;\
    for (int i = 0; i < limit; i++)
        r[i] = ( r[i >> 1] >> 1 ) | ( (i & 1) << (l - 1) ) ;
    // 在原序列中 i 与 i/2 的关系是 : i可以看做是i/2的二进制上的每一位左移一位得来
    // 那么在反转后的数组中就需要右移一位,同时特殊处理一下奇数
    FFT(a, 1);
    FFT(b, 1);
    for (int i = 0; i < limit; i++) a[i] = a[i] * b[i];
    FFT(a, -1);
    for (int i = 0; i <= N + M; i++)
        cout<<(int)(a[i].x/limit+0.5)<<' ';
    return 0;
}
posted @ 2026-01-07 15:03  wtnbl  阅读(3)  评论(0)    收藏  举报