c++复数类太慢了。。。于是就自己写了一个。。。、
FFT是很有意思的算法,可以尝试自己去写写。
本记录:http://uoj.ac/submission/13994
FFT 流程 :
- A−>a
- B−>b
- a∗b=c
- c−>C
*大写字母表示系数表示法,小写字母表示点值表示法
时间复杂度: O(N∗log2N) , 具体实现见《算法导论》
#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;
}