Polynomial Multiplication

Polynomial multiplication is a binary operation that takes two polynomials as inputs and produces a polynomial.

P(x)=a0+a1x1+a2x2+...+anxn1P(x)=a_0+a_1x^1+a_2x^2+...+a_nx^{n-1}

Now Given

A(x)=i=0n1aixiA(x)=\sum_{i=0}^{n-1}a_ix^i

B(x)=i=0m1bixiB(x)=\sum_{i=0}^{m-1}b_ix^i

C(x)=A(x)B(x)C(x)=A(x)B(x)

C is called the convolution of A and B.


Problem: How to multiply two polynomials in O(nlogn)O(n\log n) time

To solve the problem, we need to apply the Fast Fourier Transform (FFT) algorithm, rather than the traditional method of multiplying each term of one polynomial by each term of the other polynomial. Then it it suffices to answer: How to multiply two polynomials using FFT?

DFT

There is two forms of representation of a polynomial. One is the coefficient form and another is the point-value form. The point-value form is the value of the polynomial at some points. The Discrete Fourier Transform (DFT) is a transformation that converts a polynomial from the coefficient form to the point-value form.

IDFT

The inverse DFT converts a polynomial from the point-value form to the coefficient form.

FFT

We have to evaluate the polynomial at o=n+mo=n+m points. The simple operation costs O(n2)O(n^2) time. There is a better way to do this in O(nlogn)O(n\log n) time:

Root of unity

Let ωnk\omega_n^k denotes the kthk^{th} root of unity of order nn. Namely, ωnk=cos2πkn1+isin2πkn1=e2πkn1\omega_n^k=\cos \frac{2\pi k}{n-1}+i\sin \frac{2\pi k}{n-1}=e^{\frac{2\pi k}{n-1}}

It can be easily proved that

  1. ωnk\omega_n^k= ω2n2k\omega_{2n}^{2k}
  2. ωnk=ωnk+n2\omega_n^k=-\omega_n^{k+\frac{n}{2}}(assert n is even)
  3. ωnkωnl=ωnk+l\omega_n^k\cdot\omega_n^l=\omega_n^{k+l}

We just need to evaluate the polynomial at ωn0,ωn1,...,ωnn1\omega_n^0,\omega_n^1,...,\omega_n^{n-1}.

Assert n is even, if n is odd, we can add a zero term to the polynomial.

For 0k<n/20\le k<n/2, we have

P(ωnk)=a0+a1ωnk+a2(ωnk)2+...+an(ωnk)n1=(a0+a2(ωnk)2+a4(ωnk)4a+...+an1(ωnk)n2)+ωnk(a1+...+an(ωnk)n2)=(a0+a2ωn2k+a4(ωn2k)2+...+an(ωn2k)n21)+ωnk(a1+...+an(ωn2k)n21)=R(ωn2k)+ωnkS(ωn2k)\begin{aligned} P(\omega_n^k)&=a_0+a_1\omega_n^k+a_2(\omega_n^k)^2+...+a_n(\omega_n^k)^{n-1} \\ &=(a_0+a_2(\omega_n^k)^2+a_4(\omega_n^k)^4a+...+a_{n-1}(\omega_n^k)^{n-2})+\omega_n^k(a_1+...+a_n(\omega_n^k)^{n-2})\\ &= (a_0+a_2\omega_{\frac{n}{2}}^k+a_4(\omega_{\frac{n}{2}}^k)^2+...+a_n(\omega_{\frac{n}{2}}^k)^{\frac{n}{2}-1})+\omega_n^k(a_1+...+a_{n}(\omega_{\frac{n}{2}}^k)^{\frac{n}{2}-1}) \\ &= R(\omega_{\frac{n}{2}}^k)+\omega_n^kS(\omega_{\frac{n}{2}}^k) \end{aligned}

And for P(ωnk+n2)P(\omega_n^{k+\frac{n}{2}}) we have

P(ωnk+n2)=P(ωnk)=R(ωn2k)ωnkS(ωn2k)\begin{aligned} P(\omega_n^{k+\frac{n}{2}})=P(-\omega_n^{k})=R(\omega_{\frac{n}{2}}^k)-\omega_n^kS(\omega_{\frac{n}{2}}^k) \end{aligned}

Then the problem is divided into two subproblems of size n2\frac{n}{2}. We can solve the problem recursively.

Why Does FFT Save Time: For every recursion, we have R(ωn2k) and S(ωn2k)R(\omega_{\frac{n}{2}}^k)\text{ and } S(\omega_{\frac{n}{2}}^k), so we could get P(ωnk) and P(ωnk+n2)P(\omega_n^k)\text{ and }P(\omega_n^{k+\frac{n}{2}}) at the same time(even if we do not need R(ωn2k) and S(ωn2k)R(\omega_{\frac{n}{2}}^k)\text{ and } S(\omega_{\frac{n}{2}}^k) in lower layers for calculating the value at one point, it makes sense for n points)

Time complexity

For k from 0 to n-1, calculating the DFT of two halves of P(ωnk)P(\omega_n^k) costs T(n2)T(\frac{n}{2}) time.
Adding the two halves of P(ωnk)P(\omega_n^k) costs O(n)O(n) time.

T(n)=2T(n2)+O(n)T(n)=2T(\frac{n}{2})+O(n)

In total, the time complexity is O(nlogn)O(n\log n).


Now we have the point-value form of the polynomial, Let P(ωnk)=vk.P(\omega_n^k)=v_k.

Let Q(x)=v0+v1x+v2x2+...+vnxn1Q(x)=v_0+v_1x+v_2x^2+...+v_nx^{n-1}

Q(ωnk)=i=0n1vi(ωnk)i=i=0n1viωnik=i=0n1j=0n1ajωnijωnik=j=0n1aji=0n1ωni(jk)=j=0n1aji=0n1(ωnjk)i=j=0n1najδj,k=naj\begin{aligned} Q(\omega_n^{-k})&=\sum_{i=0}^{n-1}v_i(\omega_n^{-k})^i\\ &=\sum_{i=0}^{n-1}v_i\omega_n^{-ik}\\ &=\sum_{i=0}^{n-1}\sum_{j=0}^{n-1}a_j\omega_n^{ij}\omega_n^{-ik}\\ &=\sum_{j=0}^{n-1}a_j\sum_{i=0}^{n-1}\omega_n^{i(j-k)}\\ &=\sum_{j=0}^{n-1}a_j\sum_{i=0}^{n-1}(\omega_n^{j-k})^{i}\\ &=\sum_{j=0}^{n-1}na_j\delta_{j,k}\\ &=na_j \end{aligned}

How to calculate Q(ωnk)Q(\omega_n^{-k})

Use the FFT algorithm to calculate the point-value form of the polynomial. Then we can get the coefficient form of the polynomial.

Time complexity

The same as DFT, O(nlogn)O(n\log n).

Now we can multiply two polynomials in O(nlogn)O(n\log n) time.


电波交流