FFT 模板

FFT(Fast Fourier Transformation/快速傅立叶变换),确切地说应该称之为FDFT(Fast Discrete Fourier Transformation/快速离散傅立叶变换),因为FFT是为解DFT问题而设计的一种快速算法。在深入讨论之前,有必要特别指出这一点。

DFT问题:

给定一个复数域上的n-1次多项式A(x)的系数表示(cofficient representation)(a[0], a[1], ..., a[n-1]),求A(x)的某个点-值表示(point-value representation)。

递归FFT的实现(《算法导论》)

 1 #include <bits/stdc++.h>
 2 #define rep(i, l, r) for(int i=l; i<r; i++)
 3 using namespace std;
 4 const double PI(acos(-1));
 5
 6 struct P{
 7     double r, i;
 8     P(double r, double i):r(r), i(i){}
 9     P(int n):r(cos(2*PI/n)), i(sin(2*PI/n)){}    //!!error-prone
10     P():r(0), i(0){}    //default constructor
11     void operator *=(const P &a){
12         double R=r*a.r-i*a.i, I=r*a.i+a.r*i;
13         r=R, i=I;
14     }
15     P operator+(const P a){
16         return P(r+a.r, i+a.i);
17     }
18     P operator-(const P a){
19         return P(r-a.r, i-a.i);
20     }
21     P operator*(const P a){
22         return P(r*a.r-i*a.i, r*a.i+a.r*i);
23     }
24     void out(){
25         // cout<<r<<‘ ‘<<i<<endl;
26     }
27 };
28
29
30 typedef vector<P> vec;
31
32 vec FFT(vec a, int t){
33     int n=a.size();    //n is a power of 2
34     if(n==1) return a;
35     P wn(t*n), w(1, 0);
36     vec b[2], y[2];
37     for(int i=0; i<n; i++)
38         b[i%2].push_back(a[i]);
39
40     y[0]=FFT(b[0], t), y[1]=FFT(b[1], t);
41     vec res(n);
42     for(int i=0, h=n>>1; i<h; i++){
43         res[i]=y[0][i]+w*y[1][i];
44         res[i+h]=y[0][i]-w*y[1][i];
45         w*=wn;
46     }
47     return res;
48 }
49
50 const int N(5e4+5);
51 char s[N], t[N];
52
53 int trans(int x){
54     int i=0;
55     for(; x>1<<i; i++);
56     return 1<<i;
57 }
58
59 vec a, b, Y1, y2, res;
60
61 int ans[N];
62
63 int main(){
64     for(; ~scanf("%s%s", s, t); ){
65         int n=strlen(s), m=strlen(t), l=trans(n+m-1);
66         a.clear(), b.clear();    //error-prone
67         for(int i=0; i<n; i++) a.push_back(P(s[n-1-i]-‘0‘, 0)); a.resize(l);    //error-prone
68         for(int i=0; i<m; i++) b.push_back(P(t[m-1-i]-‘0‘, 0)); b.resize(l);
69         Y1=FFT(a, 1), y2=FFT(b, 1);
70         rep(i, 0, l) Y1[i]*=y2[i];
71         res=FFT(Y1, -1);
72         rep(i, 0, l) res[i].r/=l;    //error-prone
73         rep(i, 0, l) ans[i]=(int)(res[i].r+0.5); ans[l]=0;    //error-prone
74         rep(i, 0, l) ans[i+1]+=ans[i]/10, ans[i]%=10;
75         int p=l;
76         for(;p && !ans[p]; --p);
77         for(; ~p; putchar(ans[p--]+‘0‘));    //error-prone
78         puts("");
79     }
80     return 0;
81 }

Comment:

1. 此代码是为HDU1402写的。代码中,凡注释error-prone处,都应特别小心。我犯的最傻逼的错误是第9行,应当是2*PI,我写成PI了。

2. 这个FFT的递归实现完全是参照《算法导论》(3rd. Ed. Chapter 30, Polynomials and the FFT) 的,但这个实现常数大,空间复杂度高,TLE了

3. 迭代实现后面会补上

4. FFT的数值稳定性(精度)问题,还有待考虑。

时间: 2024-10-14 22:43:49

FFT 模板的相关文章

再写FFT模板

没什么好说的,今天有考了FFT(虽然不用FFT也能过)但是确实有忘了怎么写FFT了,于是乎只有重新写一遍FFT模板练一下手了.第一部分普通FFT,第二部分数论FFT,记一下模数2^23*7*17+1 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; typedef double

fft模板 HDU 1402

1 // fft模板 HDU 1402 2 3 #include <iostream> 4 #include <cstdio> 5 #include <cstdlib> 6 #include <algorithm> 7 #include <vector> 8 #include <math.h> 9 #include <memory.h> 10 #include <bits/stdc++.h> 11 using

hdu1402(大数a*b&amp;fft模板)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1402 题意: 给出两个长度1e5以内的大数a, b, 输出 a * b. 思路: fft模板 详情参见: http://blog.csdn.net/sdj222555/article/details/9786527  https://wenku.baidu.com/view/8bfb0bd476a20029bd642d85.html 可以将 a, b 看成两个多项式, 每个数位为一项, 每一位上的

FFT模板

  #include <cstdio> #include <cmath> #include <cstring> using namespace std; const double pi = acos(-1.0); const int maxn = 500005; struct complex { double r,i; complex(double r = 0.0,double i = 0.0) :r(r),i(i) {} inline complex operator

[hdu1402]大数乘法(FFT模板)

题意:大数乘法 思路:FFT模板 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

【BZOJ 2179】【FFT模板】 FFT快速傅立叶

2179: FFT快速傅立叶 Time Limit: 10 Sec Memory Limit: 259 MB Submit: 1595 Solved: 792 [Submit][Status][Discuss] Description 给出两个n位10进制整数x和y,你需要计算x*y. Input 第一行一个正整数n. 第二行描述一个位数为n的正整数x. 第三行描述一个位数为n的正整数y. Output 输出一行,即x*y的结果. Sample Input 1 3 4 Sample Output

【bzoj2179】FFT快速傅立叶 FFT模板

2016-06-01  09:34:54 很久很久很久以前写的了... 今天又比较了一下效率,貌似手写复数要快很多. 贴一下模板: 1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 #includ

高精度乘法FFT 模板

渣模板,不知为何常数还挺大.. CODE: #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 200010 #define PI 3.1415926535897932384626 using namespace std; struct Complex{ double real,imag

FFT模板(From MG)

1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 using namespace std; 5 struct cp{double x,y;}; 6 int n1,n2,n,m; 7 double pi=acos(-1); 8 cp a[500010],b[500010],cur[500010]; 9 cp operator *(cp x,cp y){return (cp){x.x*y.x-x.y*y