Fast Fourier Transform


c++复数类太慢了。。。于是就自己写了一个。。。、
FFT是很有意思的算法,可以尝试自己去写写。

提交地址:http://uoj.ac/problem/34

本记录:http://uoj.ac/submission/13994



FFT 流程 :

  • A>a
  • B>b
  • ab=c
  • c>C

*大写字母表示系数表示法,小写字母表示点值表示法

时间复杂度: O(Nlog2N) , 具体实现见《算法导论》



#include<map>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<iostream>
#include<algorithm>

const int MAXN = 1e5+5,MAXM = 1e5+5;
const double pi = acos(-1);

struct complex{double x,yi; complex(double x = 0,double yi = 0):x(x),yi(yi){}};
complex operator + (const complex &a,const complex &b){return complex(a.x + b.x,a.yi + b.yi);}
complex operator - (const complex &a,const complex &b){return complex(a.x - b.x,a.yi - b.yi);}
complex operator * (const complex &a,const complex &b){return complex(a.x*b.x - a.yi*b.yi , a.x*b.yi + a.yi*b.x);}
complex operator / (const complex &a,const double &b) {return complex(a.x/b,a.yi/b);}


void FFT(complex *X,int n,int flag)
{
    for(int i = 0; i < n; i++)
    {
        int p = 0, t = i;
        for(int j = 1; j < n; j <<= 1)
          p <<= 1, p |= (t&1), t >>= 1;
        if(i < p) std::swap(X[i], X[p]);
    }
    for(int m = 2; m <= n; m <<= 1)
    {
        complex wm = complex(cos((double)2*pi*flag/m), sin((double)2*pi*flag/m));
        for(int i = 0 ; i < n; i += m)
        { 
            complex wk = complex(1, 0); 
            for(int j = 0; j < (m>>1); wk = wk*wm, j++)
            {
                complex u = X[i+j], t = wk*X[i+j+(m>>1)];
                X[i+j] = u + t, X[i+j+(m>>1)] = u - t;
            }
        }
    }
    if(flag == -1) for(int i = 0; i < n; i++) X[i] = X[i]/n;
}
int main()
{
    int l, N , n , m;
    static complex A[MAXN<<2] , B[MAXM<<2], C[(MAXN+MAXM)<<1];

#ifndef ONLINE_JUDGE
    freopen("FFT.in","r",stdin);
    freopen("FFT.out","w",stdout);
#endif

    std::cin >> n >> m; 

    l = n + m + 1, N = 1; 
    while(N < l) N <<=1;

    for(int i = 0; i <= n; i++)scanf("%lf",&A[i].x);
    for(int i = 0; i <= m; i++)scanf("%lf",&B[i].x);

    FFT(A, N, 1);FFT(B, N, 1);
    for(int i = 0; i < N; i++) C[i] = A[i]*B[i];
    FFT(C, N, -1);

    for(int i = 0; i < l; i++) printf("%d ", (int)(C[i].x+0.5));

#ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
#endif
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值