How to multiply polynomials in Θ(n log n) time
agarri.ga
agarri.ga
In this case the issue is that you need more and more precision for the FFT as the inputs get larger, or else you'll get the wrong answer. I think it ends up being an O(n log^2 n) algorithm. Still pretty good; worth knowing about for sure. The constant factor on the precision might be bad enough that you can trigger the problem for reasonable inputs if you're using floats (e.g. a million coefficients, instead of an octillion coefficients).
On the other hand, many algorithms and data structures have hidden logarithmic factors (e.g. hash tables, sorting) that we ignore [1]. YMMV.
1: http://blog.computationalcomplexity.org/2009/05/shaving-logs...
As you say, you can always convert to an integer multiplication problem so it stands at O(n lg(n) lg(lg(n))) (not O(n lg^2(n))).
Multiplication of polynomials when expressed in the domain of "array of coefficients" is a convolution operation: really you're summing (AB)_k = sum_{i=0}^k A_i B_{k-i} to find the kth coefficient of the result. The indices for B go backwards to those of A and they add up to the fixed quantity k, so we're just looking at a discrete convolution of these two arrays.
And what does Fourier Transform do? It turns convolutions into point-wise multiplication in the 'time' domain. The convolution started as an n^2 operation but the point-wise multiplication is n, so we're left with the FFT time of n log n. So this is another instance of the "formulate problem as a convolution, FFT, perform point-wise multiplication in the time domain, inverse FFT, done" class of algorithms.
(I got stuck a while trying to figure out how polynomial multiplication is convolution. Literally it's point-wise multiplication of two functions, not a convolution, so everything seemed backwards.)
I had not understood properly on first read of your comment, but you did not mean what is on the post at all. I'll include this insight somehow :)
Don't you mean signal domain though?
Anyone trying to work with polynomials as continuous functions using floating point arithmetic (or trying to work efficiently with piecewise continuous functions in general) should check out Chebfun, http://www.chebfun.org
People should avoid working with polynomials expressed in the monomial basis if possible, unless dealing with a function defined on the complex unit circle. The Chebyshev basis is generally faster and more accurate for polynomials defined on some real interval, and makes it practical to compute with polynomials of very high degree. http://www.chebfun.org/examples/linalg/CondNos.html http://www.chebfun.org/examples/roots/RandomPolynomials.html
For a lot more see: http://www.chebfun.org/ATAP/atap-first6chapters.pdf http://www.chebfun.org/docs/guide/chebfun_guide.pdf
Here’s the guts of their multiplication routine, which multiplies two polynomials and returns a new polynomial which approximates the product to near machine precision: https://github.com/chebfun/chebfun/blob/development/%40chebt... (For the mathematical details see the (paywalled) paper http://epubs.siam.org/doi/abs/10.1137/120865458?journalCode=...). Multiplying values at Chebyshev points (similar to the blog post under discussion) would work too, but Chebfun natively stores an array of coefficients. In fact, they did multiply at values before April of last year, https://github.com/chebfun/chebfun/blob/05611dec557718b5b026...
As a physicist my first thought would be that convolution is simply multiplying in Fourier-space anyway, no need to think about polynomials. I didn't know the application of FFT for polynomials though so thanks for that.
Edit: Solved. I've missed that the problem only deals with change amounts that can be reached with one or two coins. So a single convolution is sufficient in this specific case.
But anyway, coin change problem can be solved much faster. http://link.springer.com/article/10.1007%2Fs00453-007-0162-8
(Note that for integers, a post-processing step is necessary to account for coefficients that are larger than the number base, but I guess this is relatively inexpensive).
This correspondence is often exploited in both directions. If you ask a sufficiently sophisticated computer algebra system (SageMath, for example) to multiply two large polynomials with integer or rational coefficients, chances are that it will reduce the problem to multiplying two large integers, then reduce that problem to multiplying two large polynomials (but different from the ones you started with), and then proceed using recursive polynomial and integer multiplications to compute that product... (i.e. going through a sequence of transformations Z[x] -> Z -> Z[x] -> ...)
Deleted comment
> So how do we do it? We are going to have to talk a bit about the representation of polynomials in computer memory first. (Haha get it?)
Without that hint I would have totally missed it.
Also, this could be a joke on the joke. Probably the author didn't really think this pun is funny, and made fun of themselves by overstating how funny that pun is. Humor is a large field with lots of varieties. (And no, I will not spoil that this is a maths pun.)