多项式乘法 (快速傅里叶变换)

算法导论里基本看懂了傅里叶变换的整个运行流程。

后面剩下的就是如何规划设计程序,使得程序漂亮又高效,暂时没时间,先做个记录,后面慢慢实现。



http://blog.miskcoo.com/2015/04/polynomial-multiplication-and-fast-fourier-transform


https://www.zybuluo.com/397915842/note/37965

网上摘录某段代码,可供参考:

#include
2.#include
3.#include
4.const int MAXN = 2e5 + 5;
5.const double PI = acos(-1.0);
6.#define max(a, b) (a) > (b) ? (a) : (b)
7.
8.class Complex
9.{
10.public:
11.    double real, imag;
12.
13.    Complex(double real = 0.0, double imag = 0.0)
14.    {
15.        this->real = real, this->imag = imag;
16.    }
17.
18.    Complex operator - (const Complex &elem) const
19.    {
20.        return Complex(this->real - elem.real, this->imag - elem.imag);
21.    }
22.
23.    Complex operator + (const Complex &elem) const
24.    {
25.        return Complex(this->real + elem.real, this->imag + elem.imag);
26.    }
27.
28.    Complex operator * (const Complex &elem) const
29.    {
30.        return Complex(this->real * elem.real - this->imag * elem.imag, this->real * elem.imag + this->imag * elem.real);
31.    }
32.
33.    void setValue(double real = 0.0, double imag = 0.0)
34.    {
35.        this->real = real, this->imag = imag;
36.    }
37.};
38.
39.Complex A[MAXN], B[MAXN];
40.int res[MAXN], len, mlen, len1, len2;
41.char str1[MAXN >> 1], str2[MAXN >> 1];
42.
43.void Swap(Complex &a, Complex &b)
44.{
45.    Complex tmp = a;
46.    a = b;
47.    b = tmp;
48.}
49.
50.void Prepare()
51.{
52.    len1 = strlen(str1), len2 = strlen(str2);
53.    mlen = max(len1, len2);
54.    len = 1;
55.
56.    // 将 len 扩大到 2 的整数幂
57.    while(len < (mlen << 1))
58.        len <<= 1;
59.
60.    //初始化多项式的系数
61.    for(int i = 0; i < len1; ++ i)
62.        A[i].setValue(str1[len1 - i - 1] - '0', 0);
63.
64.    for(int i = 0; i < len2; ++ i)
65.        B[i].setValue(str2[len2 - i - 1] - '0', 0);
66.
67.    // 补 0
68.    for(int i = len1; i < len; ++ i)
69.        A[i].setValue();
70.
71.    for(int i = len2; i < len; ++ i)
72.        B[i].setValue();
73.}
74.
75.//雷德算法 位逆序置换
76.void Rader(Complex y[])
77.{
78.    for(int i = 1, j = len >> 1, k; i < len - 1; ++ i)
79.    {
80.        if(i < j)
81.            Swap(y[i], y[j]);
82.
83.        k = len >> 1;
84.
85.        while(j >= k)
86.        {
87.            j -= k;
88.            k >>= 1;
89.        }
90.
91.        if(j < k)
92.            j += k;
93.    }
94.}
95.
96.//DFT : op == 1
97.//IDFT : op == -1
98.void FFT(Complex y[], int op)
99.{
100.    //先位逆序置换
101.    Rader(y);
102.
103.    // h 为每次要处理的长度, h = 1 时不需处理
104.    for(int h = 2; h <= len; h <<= 1)
105.    {
106.        // Wn = e^(2 * PI / n),如果是插值,那么 Wn = e^(-2 * PI / n)
107.        Complex Wn(cos(op * 2 * PI / h), sin(op * 2 * PI / h));
108.
109.        for(int i = 0; i < len; i += h)
110.        {
111.            //旋转因子,初始化为 e^0
112.            Complex W(1, 0);
113.
114.            for(int j = i; j < i + h / 2; ++ j)
115.            {
116.                Complex u = y[j];
117.                Complex t = W * y[j + h / 2];
118.                //蝴蝶操作
119.                y[j] = u + t;
120.                y[j + h / 2] = u - t;
121.                //每次更新旋转因子
122.                W = W * Wn;
123.            }
124.        }
125.    }
126.
127.    // 插值的时候要除以 len
128.    if(op == -1)
129.        for(int i = 0; i < len; ++ i)
130.            y[i].real /= len;
131.}
132.
133.//DFT 后将 A 和 B 相应点值相乘,将结果放到 res 里面
134.void Convolution(Complex *A, Complex *B)
135.{
136.    //evaluation
137.    FFT(A, 1), FFT(B, 1);
138.
139.    for(int i = 0; i < len; ++ i)
140.        A[i] = A[i] * B[i];
141.
142.    //interpolation
143.    FFT(A, -1);
144.
145.    for(int i = 0; i < len; ++ i)
146.        res[i] = (int)(A[i].real + 0.5);
147.}
148.
149.void Adjustment(int *arr)
150.{
151.    //次数界为 len,所以不用担心进位不会进到第 len 位
152.    for(int i = 0; i < len; ++ i)
153.    {
154.        res[i + 1] += res[i] / 10;
155.        res[i] %= 10;
156.    }
157.
158.    //去除多余的 0
159.    while(-- len && res[len] == 0);
160.}
161.
162.void Display(int *arr)
163.{
164.    for(int i = len; i >= 0; -- i)
165.        putchar(arr[i] + '0');
166.
167.    putchar('\n');
168.}
169.
170.int main()
171.{
172.    while(gets(str1) && gets(str2))
173.    {
174.        Prepare();
175.        Convolution(A, B);
176.        Adjustment(res);
177.        Display(res);
178.    }
179.
180.    return 0;
181.}































你可能感兴趣的:(随记)