使用 radix-2 快速傅里叶变换的快速多项式乘法算法介绍
使用 radix-2 快速傅里叶变换(FFT)来实现快速多项式乘法是一种高效的算法,尤其在处理大规模数据时。其基本思想是利用 FFT 将两个多项式转换到点值表示,然后在点值表示下进行乘法操作,最后再通过逆 FFT(IFFT)转换回系数表示。
步骤分解
- 多项式转点值表示
假设有两个多项式 A ( x ) = a 0 + a 1 x + a 2 x 2 + ⋯ + a n − 1 x n − 1 A(x)=a _0+a _1x+a _2x ^2+⋯+a _{n−1}x ^{n−1} A(x)=a0+a1x+a2x2+⋯+an−1xn−1和
B ( x ) = b 0 + b 1 x + b 2 x 2 + ⋯ + b n − 1 x n − 1 B(x)=b_0+b_1x+b_2x ^2+⋯+b_{n−1}x^{n−1} B(x)=b0+b1x+b2x2+⋯+bn−1xn−1。
选择n 个不同的 x 值(通常是 n 次单位根或其幂),使用 FFT 将 A(x) 和 B(x) 转换到点值表示。
FFT 的 radix-2 版本通过递归地将多项式分解成更小的部分,并利用单位根的对称性质来减少计算量。 - 点值乘法
在点值表示下,两个多项式的乘积非常简单: C ( x i ) = A ( x i ) ⋅ B ( x i ) C(x_i)=A(x_i)⋅B(x_i) C(xi)=A(xi)⋅B(xi),其中 x i x_i xi是所选的 n 个不同的 x 值之一。 - 逆 FFT 转换回系数表示
使用逆 FFT (IFFT) 将 C ( x ) C(x) C(x)的点值表示转换回系数表示,得到 C ( x ) = C 0 + C 1 x + C 2 x 2 + ⋯ + C 2 n − 2 x 2 n − 2 C(x)=C _0+C _1x+C _2x ^2+⋯+C _{2n−2}x ^{2n−2} C(x)=C0+C1x+C2x2+⋯+C2n−2x2n−2
注意:由于我们是从n 次多项式开始,结果 C(x) 的最高次项是 2n−2,但实际上我们只关心前 n 个系数(即 c 0 c_0 c0到 c n − 1 c_{n−1} cn−1 ),因为它们是 A ( x ) ⋅ B ( x ) A(x)⋅B(x) A(x)⋅B(x) 的系数。
伪代码如下
function FastPolynomialMultiply(A, B):
n = length(A)
if n != length(B):
throw "Polynomials must have the same degree"
# 填充 A 和 B 到 2n-1 长度(为 FFT 做准备)
A_padded = pad_zeros(A, 2*n-1)
B_padded = pad_zeros(B, 2*n-1)
# FFT 转换到点值表示
A_fft = FFT(A_padded)
B_fft = FFT(B_padded)
# 点值乘法
C_fft = [A_fft[i] * B_fft[i] for i in range(2*n-1)]
# 逆 FFT 转换回系数表示
C = IFFT(C_fft)
使用 radix-2 快速傅里叶变换的快速多项式乘法算法python实现样例
下面是使用 radix-2 快速傅里叶变换(FFT)的快速多项式乘法算法的 Python 实现:
import numpy as np
def fft(a):
n = len(a)
if n <= 1:
return a
even = fft(a[0::2])
odd = fft(a[1::2])
t = np.exp(-2j * np.pi * np.arange(n) / n)
return np.concatenate([even + t[:n//2] * odd, even + t[n//2:] * odd])
def ifft(a):
n = len(a)
if n <= 1:
return a
even = ifft(a[0::2])
odd = ifft(a[1::2])
t = np.exp(2j * np.pi * np.arange(n) / n)
return np.concatenate([even + t[:n//2] * odd, even + t[n//2:] * odd]) / 2
def multiply_polynomials(a, b):
n = len(a) + len(b) - 1
size = 1 << (n - 1).bit_length()
a = np.pad(a, (0, size - len(a)))
b = np.pad(b, (0, size - len(b)))
fa = fft(a)
fb = fft(b)
result = ifft(fa * fb)
return np.rint(result).astype(int).tolist()
# 示例用法
a = [3, 2, 5]
b = [1, 4, 6]
result = multiply_polynomials(a, b)
print(result)
在上面的代码中,首先实现了 FFT 和 IFFT 函数,它们分别用于计算傅里叶变换和逆傅里叶变换。然后实现了 multiply_polynomials
函数,该函数用于将两个多项式相乘。具体步骤如下:
- 获取两个多项式的长度,并计算乘积多项式的长度。
- 将输入多项式分别补零使其长度为 2 的幂次,并进行傅里叶变换得到频域表示。
- 将两个多项式在频域中进行点乘。
- 对点乘结果进行逆傅里叶变换得到乘积多项式的系数。
- 将乘积多项式的系数四舍五入并转换为整数类型。
- 返回乘积多项式的系数列表。
上述代码中使用了 numpy
库来进行数组操作和数学计算。如果未安装 numpy
,可以使用以下命令进行安装:
pip install numpy
通过运行上述代码,将会输出乘积多项式的系数列表 [3, 14, 34, 44, 30]
。