A polynomial of degree is uniquely determined by its values at distinct points:
General points —
long long lagrange(const vector<long long>& x, const vector<long long>& y,
long long target, long long MOD) {
int n = x.size();
long long res = 0;
for (int i = 0; i < n; i++) {
long long num = 1, den = 1;
for (int j = 0; j < n; j++) {
if (j == i) continue;
num = num * ((target - x[j]) % MOD + MOD) % MOD;
den = den * ((x[i] - x[j]) % MOD + MOD) % MOD;
}
res = (res + y[i] % MOD * num % MOD * powmod(den, MOD - 2, MOD)) % MOD;
}
return res;
}with a modpow per term; if you batch the inverses.
Consecutive points —
When the sample points are , the products telescope into factorials:
with and — both computable as prefix and suffix products.
long long lagrangeConsecutive(const vector<long long>& y, long long k, long long MOD) {
int n = y.size(); // points x = 0..n-1
if (k < n) return y[k];
vector<long long> pre(n + 1, 1), suf(n + 1, 1);
for (int i = 0; i < n; i++) pre[i+1] = pre[i] * ((k - i) % MOD) % MOD;
for (int i = n - 1; i >= 0; i--) suf[i] = suf[i+1] * ((k - i) % MOD) % MOD;
long long res = 0;
for (int i = 0; i < n; i++) {
long long num = pre[i] * suf[i+1] % MOD;
long long den = invFact[i] * invFact[n-1-i] % MOD;
long long term = y[i] * num % MOD * den % MOD;
res = ((n - 1 - i) & 1) ? (res - term + MOD) % MOD : (res + term) % MOD;
}
return res;
}after precomputing factorials — this is the version that appears in contests.
The killer application: sums of powers
is a polynomial in of degree . So compute by brute force in , then interpolate to get for up to in .
long long powerSum(long long n, int k, long long MOD) {
vector<long long> y(k + 2, 0);
for (int i = 1; i <= k + 1; i++)
y[i] = (y[i-1] + powmod(i, k, MOD)) % MOD;
return lagrangeConsecutive(y, n, MOD); // points 0..k+1
}The same trick handles any quantity known to be polynomial in : prefix sums of a polynomial, counts satisfying a polynomial formula, and DP answers that are eventually polynomial.
Recognising “the answer is a polynomial”
This is the real skill. Signals:
- the answer is a sum of a polynomial over a range → degree increases by 1;
- the answer counts lattice points in a region scaling linearly with (Ehrhart polynomials);
- a DP whose transition is linear with constant coefficients, evaluated at ;
- the problem gives huge but the structure only depends on a small degree.
Verification: compute the first values by brute force, interpolate from the first , and check that the predicted values match the rest. If they do, the degree guess is right.
Fast interpolation and evaluation
| Task | Naive | Fast |
|---|---|---|
| Value at one point, general | — | |
| Value at one point, consecutive | — | |
| Coefficients from points | ||
| Values at new points | (multipoint) | |
| Shift |
Newton’s divided differences
An alternative form that allows adding points incrementally:
with the computed by a divided-difference table. to build, but adding one new point is rather than a full rebuild — useful when the sample set grows.
Pitfalls
Three traps
- Repeated makes the denominator zero. Deduplicate first.
- Wrong degree. Interpolating points assumes degree ; if the true degree is higher, the answer is silently wrong. Always verify with extra points.
- The target coincides with a sample point. Return directly rather than dividing by zero.
See also: Multipoint Evaluation · Polynomial Arithmetic · Combinatorics