MULTIPLY-FFT(a, b, n) convert binary numbers a, b into polynomials A, B of degree n m = 2 ^ (⌈lg n⌉ + 1) for i = 1 to m - n INSERT(A, 0) INSERT(B, 0) C = FFT-INV(FFT(A, m) ⋅ FFT(B, m), m) cap = 0 for i = 0 to m - 1 cap = cap + C[i] C[i] = cap % 2 cap = ⌊cap / 2⌋ convert polynomial C to binary number c return c
COMPUTE-DERIVATIVE-BY-FFT(A, n, x) m = 2 ^ (⌈lg n⌉ + 1) for i = 1 to m - n INSERT(A, 0) let F[0 : m - 1], H[0 : m - 1] ,fac[0, m - 1] be new arrays fac[0] = 1 for i = 1 to n - 1 fac[i] = fac[i - 1] * i for i = 0 to n - 1 F[i] = A[i] * fac[i] l = i - (n - 1) H[i] = exp(x, -l) / fac[-l] Y = FFT-INV(FFT(F, m) ⋅ FFT(H, m), m) let Z[0 : m - 1], D[0 : n - 1] be new arrays for i = 0 to n - 1 Z[i] = Y[i + m / 2] / fac[i] B = FFT-INV(Z, m) for i = 0 to n - 1 D[i] = B[i] * fac[i] return 0
// 假设函数PLOY-MULTIPLY和POLY-MODULO会将多项式的长度拓展成2的幂,并且用FFT和FFT-INV分别作为子程序运行,以O(n lg n)的时间进行,这里忽略了实现细节。 EVALUATE-N-VALUES(A, X, n) m = 2 ^ (⌈lg n⌉) c = ⌈lg n⌉ for i = 0 to m if i < n P_{ii} = [-X[i], 1] else P_{ii} = [1, 0] for k = 1 to c for l = 0 to m by 2^k r = l + 2 ^ k - 1 P_{l, r} = PLOY-MULTIPLY(P_{l, l + 2 ^ (k - 1) - 1}, P_{l + 2 ^ (k - 1), r}) Q_{0, m - 1} = A for k = c to 1 for l = 0 to m by 2^k r = l + 2 ^ k - 1 Q_{l, l + 2 ^ (k - 1) - 1} = PLOY-MODULO(Q_{l, r}, P_{l + 2 ^ (k - 1), r}) Q_{l + 2 ^ (k - 1), r} = PLOY-MODULO(Q_{l, r}, P_{l, l + 2 ^ (k - 1) - 1}) let Y[0 : n - 1] be a new array for i = 0 to n - 1 Y[i] = Q_{ii} return Y
FFT-OVER-RING(a, n, p, wn) if n == 1 return a w = 1 a-even = (a_0, a_2, ..., a_{n - 2}) a-odd = (a_1, a_3, ..., a_{n - 1}) y-even = FFT-INV(FFT-OVER-RING, n / 2, p, wn * wn % p) y-odd = FFT-INV(FFT-OVER-RING, n / 2, wn * wn % p) for k = 0 to n / 2 - 1 y_k = (a-even_{k} + w * a-odd_{k}) % p y_{k + n / 2} = (a-even_{k} - w * a-odd_{k}) % p w = w * wn % p return y
// wn^{-1}和n^{-1}需要提前使用扩展欧几里得算法计算好,避免重复计算,结果分别用wn-inv和n-inv表示。 FFT-INV-OVER-RING(y, n, p, wn-inv) if n == 1 return a w = 1 y-even = (y_0, y_2, ..., y_{n - 2}) y-odd = (y_1, y_3, ..., y_{n - 1}) a-even = FFT-INV-OVER-RING(y-even, n / 2, p, wn-inv * wn-inv % p) a-odd = FFT-INV-OVER-RING(y-odd, n / 2, p, wn-inv * wn-inv % p) for k = 0 to n / 2 - 1 a_k = (a-even_{k} + w * a-odd_{k}) * n-inv % p a_{k + n / 2} = (a-even_{k} - w * a-odd_{k}) * n-inv % p w = w * wn-inv % p return a