Evaluate a degree- polynomial at arbitrary points in , instead of by repeated Horner.

The idea: a product tree

Build a divide-and-conquer tree over the evaluation points, where each node stores the product over its range.

                (x-x0)(x-x1)(x-x2)(x-x3)
                /                      \
       (x-x0)(x-x1)              (x-x2)(x-x3)
        /       \                 /        \
    (x-x0)   (x-x1)           (x-x2)    (x-x3)

Building it is levels, each doing of NTT multiplication.

Evaluation — descend with remainders

By the remainder theorem, . So descend the tree, replacing by at each step. The remainder’s degree shrinks with the node’s range, so the total work per level is .

void evalRec(const Poly& P, int node, int lo, int hi, vector<long long>& out) {
    if (hi - lo == 1) { out[lo] = P.empty() ? 0 : P[0]; return; }
    int mid = (lo + hi) / 2;
    evalRec(P % tree[2*node],   2*node,   lo, mid, out);
    evalRec(P % tree[2*node+1], 2*node+1, mid, hi, out);
}

overall — the extra comes from the polynomial division at each node.

Interpolation — the reverse

Given , recover the polynomial. By Lagrange,

  1. Build the product tree and .
  2. Compute and evaluate it at all by multipoint evaluation — this gives all the denominators at once.
  3. Combine bottom-up: at each node, .

.

The cost table

TaskNaiveFast
Evaluate at 1 point
Evaluate at consecutive points (a convolution)
Evaluate at points in geometric progression (chirp-z)
Evaluate at arbitrary points
Interpolate from arbitrary points
Interpolate from consecutive points (Lagrange)

Check the point structure first

The special cases are dramatically cheaper. Consecutive points give interpolation and evaluation; geometric points give via the chirp-z transform. Only genuinely arbitrary points need the machinery — and in contests the points are usually

What it enables

ApplicationUse
Convert between coefficient and value representationsboth directions
Fast polynomial GCD (half-GCD)uses the same product-tree recursion
Polynomial factorisationevaluating at many points
Chinese remaindering of polynomialsthe same tree
$n! \bmod p$ in $\tilde O(\sqrt p)$evaluate a product polynomial at points
Shift a polynomial’s argumentvia evaluation and interpolation
Multi-modular CRT reconstructionthe integer analogue of the same tree

in

Define with . Then

and the values are a multipoint evaluation at points in arithmetic progression. Total — the standard way to compute a factorial modulo a prime when is around .

The product tree pattern

Building a balanced tree of products, then descending with remainders, is a reusable structure. The same shape appears in:

  • CRT reconstruction from many moduli in ;
  • fast polynomial GCD (half-GCD);
  • batch modular inverse (a linear special case);
  • segment trees storing products.

When it is worth it

The constant factor is significant — several NTTs per node. For , the Horner loop is faster in practice. Multipoint evaluation earns its place at , which is rare but real.

See also: Lagrange Interpolation · FFT and NTT · Polynomial Arithmetic