Q:

Given an increasing polynomial, how do you efficiently find x values for fixed intervals of y?

Problem: Given a polynomial of degree n (with coefficients a0 through an-1) that is guaranteed to be increasing from x = 0 to xmax, what is the most efficient algorithm to find the first m points with equally-spaced y values (i.e. yi - yi-1 == c, for all i)?
Example: If I want the spacing to be c = 1, and my polynomial is f(x) = x^2, then the first three points would be at y=1 (x=1), y=2 (x~=1.4142), and y=3 (x~=1.7321).

I'm not sure if it will be significant, but my specific problem involves the cube of a polynomial with given coefficients.  My intuition tells me that the most efficient solution should be the same, but I'm not sure.
I'm encountering this working through the problems in the ACM's problem set for the 2012 World Finals (problem B), so this is mostly because I'm curious.

Edit: I'm not sure if this should go on the Math SE?

A:

You can find an X for a given Y using a binary search. It's logarithmic time complexity, proportional to the size of the range of x values, divided by your error tolerance.
def solveForX(polyFunc, minX, maxX, y, epsilon):
    midX = (minX + maxX) / 2.0
    if abs(polyFunc(midX) - y) < epsilon:
        return midX
    if polyFunc(midX) > y:
        return solveForX(polyFunc, minX, midX, y, epsilon)
    else:
        return solveForX(polyFunc, midX, maxX, y, epsilon)

print solveForX(lambda x: x*x, 0, 100, 2, 0.01)

output:
1.416015625

Edit: to expand on an idea in the comments, if you know you will be searching for multiple X values, it's possible to narrow down the [minX, maxX] search range.
def solveForManyXs(polyFunc, minX, maxX, ys, epsilon):
    if len(ys) == 0:
        return []
    midIdx = len(ys) / 2
    midY = ys[midIdx]
    midX = solveForX(polyFunc, minX, maxX, midY, epsilon)
    lowYs = ys[:midIdx]
    highYs = ys[midIdx+1:]
    return solveForManyXs(polyFunc, minX, midX, lowYs, epsilon) + \
    [midX] + \
    solveForManyXs(polyFunc, midX, maxX, highYs, epsilon)

ys = [1, 2, 3]
print solveForManyXs(lambda x: x*x, 0, 100, ys, 0.01)

output:
[1.0000884532928467, 1.41448974609375, 1.7318960977718234]

