Polynomial shift is the simplest polynomial composition transform: given the coefficients of f(x)=∑i=0nfixi and a constant c, compute the coefficients of f(x+c), namely f(x)↦f(x+c).
Divide-and-Conquer Method
Let
f(x)=f0(x)+x⌊n/2⌋f1(x)
Then
f(x+c)=f0(x+c)+(x+c)⌊n/2⌋f1(x+c)
The coefficient of (x+c)⌊n/2⌋ is a binomial coefficient, so
T(n)=2T(n/2)+O(nlogn)=O(nlog2n)
where O(nlogn) is the time complexity of polynomial multiplication.
Given a polynomial f of degree at most n, together with its consecutive point values f(0),f(1),…,f(n), compute f(c),f(c+1),…,f(c+n) modulo 998244353, where 1≤n≤105,n<m≤108.
Although the formula above has a convolution form, the denominator x−i=0 is not always invertible. We therefore consider only the case c>n below; other cases (for example, when denominators of B0(x) coefficients vanish modulo a prime) can be handled by case analysis. Let
In the implementation, truncate the required part of B0(x) to obtain more point values; cyclic convolution can also be used.
With a slight modification of the problem, suppose the point values of d at f(d),f(d+k),…,f(d+nk) are given. We can compute f(c+d),f(c+d+k),…,f(c+d+nk), viewing them as the point values g(x)=f(d+kx) of the shifted polynomial g(0),g(1),…,g(n) at g(c/k),g(c/k+1),…,g(c/k+n).
The Lagrange interpolation formula also gives a linear-time method for computing one point value by maintaining several prefix and suffix products.
Applications
Unsigned Stirling Numbers of the First Kind in One Row
Example: P5408 — unsigned Stirling numbers of the first kind
Compute [0n],[1n],…,[nn] modulo the prime 167772161, where 1≤n<262144.
Consider
xn=i=0∑n[in]xi,n≥0
where xn=x⋅(x+1)⋯(x+n−1) is the rising factorial, and let fn(x)=xn. Then
f2n(x)=xn⋅(x+n)n=fn(x)fn(x+n)
Polynomial shift computes O(nlogn) in fn(x+n), reducing the problem to half its original size: compute the coefficients of fn(x). Thus
T(n)=T(n/2)+O(nlogn)=O(nlogn)
Factorial Modulo a Prime
Example: P5282 [Template] — Fast factorial algorithm
Compute n!modp, where p is prime and 1≤n<p≤231−1.
Let v=⌊n⌋ and g(x)=∏i=1v(x+i). Then
n!≡(i=0∏v−1g(iv))⋅i=v2+1∏ni(modp)
The product ∏i=v2+1ni can be computed in O(n) time. We want to compute the first product in the formula efficiently.
Polynomial Multipoint Evaluation
The coefficients of g(x) can be computed by the polynomial-shift algorithm in O(nlogn), but evaluating it at the multiple points g(0),g(v),g(2v),…,g(v2−v) takes O(nlog2n).
Continuous Point-Value Shift
Let gd(x)=∏i=1d(x+i). We can uniquely determine this degree-d polynomial from its d+1 point values gd(0),gd(v),…,gd(dv). Also,
g2d(x)=gd(x)gd(x+d)
Thus only 2d+1 point values are needed to uniquely determine g2d(x). Applying continuous point-value shift to compute gd((d+1)v),gd((d+2)v),…,gd(2dv) (that is, shift the point values h(x)=gd(vx), h(0),h(1),…,h(d) to h(d+1),h(d+2),…,h(2d)) and gd(d),gd(v+d),…,gd(2dv+d) (that is, shift the point values h(x)=gd(vx), h(0),h(1),…,h(d) to h(d/v),h(d/v+1),h(d/v+2),…,h(d/v+2d)), then multiplying the corresponding point values gives g2d(0),g2d(v),…,g2d(2dv).
To compute gd(0),gd(v),…,gd(dv) from gd+1(0),gd+1(v),…,gd+1(dv),gd+1((d+1)v), consider
gd+1(x)=(x+d+1)⋅gd(x)
The one additional point value can be obtained by a linear-time algorithm. Therefore, starting with g1(0)=1,g1(v)=v+1, we maintain these point values by repeated doubling with continuous point-value shift, obtaining
T(n)=T(n/2)+O(nlogn)=O(nlogn)
We need only about n point values, so the time complexity is O(nlogn).
Prefix Sums of Binomial Coefficients Modulo a Prime
Example: LOJ 6386 — prefix sums of binomial coefficients
Compute i=0∑m(in)mod998244353, where 0≤m≤n≤9×108.
Describe the recurrence n!=n⋅(n−1)! using matrices. We have
[n!]=(i=0∏n−1[i+1])[1]
Similarly, the recurrence for the prefix sum of binomial coefficients can be written as
Given a sequence a satisfying ∀n≥m,∑k=0man−kPk(n)=0, where Pk is a polynomial of degree at most d.
Given the coefficients of all Pk and the initial values a0,a1,…,am−1, find an. Compute modulo 998244353; n≤6×108, 1≤m,d≤7, 7s, with a time limit of {11}.
To describe the matrix constructions in the examples above more systematically, we introduce the concept of lambda matrix (λ).
For polynomial recurrences, note that the point values maintained in the fast-factorial algorithm are not actually n!, but ∏i=0T−1(aT+i): the ratio between a pair of point values.
Because the order of a polynomial recurrence, m, is no longer just 1, we cannot directly maintain the ratio between two numbers. Instead, we maintain a linear transformation between a pair of m-dimensional vectors, namely an m×m matrix; each matrix entry is the point value of a polynomial.
For a general polynomial-recurrence problem asking for a distant term, we can construct
Ignoring the leading factor −P0(n)1 for now, we need to maintain a quantity of the form ∏i=0T−1B(aT+m+i), where multiplication is performed from right to left.
It is easy to see that BT(λ)=∏i=0T−1B(λ+i) is a λ matrix whose entries have degree at most dT; it can be maintained using only dT+1 values.
We therefore maintain the point values of the BT(m) matrices BT(m+T), BT(m+2T), …, BT(m+(dT−1)T), BT(m+dT2), and λ, and use polynomial point-value shifting and doubling in the same way as in the fast-factorial algorithm.
Specifically, to lift t=log2T to 1, we proceed as follows:
In O(m2dTlog(dT)) time, obtain BT(p+dT2), BT(p+(dT+1)T), BT(p+(dT+2)T), ⋯, BT(p+(2dT−1)T), and BT(p+(2dT)dT).
In O(m2dTlog(dT)) time, obtain BT(p+2dT2), BT(p+(2dT+1)T), BT(p+(2dT+2)T), ⋯, BT(p+(3dT−1)T), and BT(p+(3dT)dT).
In O(m2dTlog(dT)) time, obtain BT(p+3dT2), BT(p+(3dT+1)T), BT(p+(3dT+2)T), ⋯, BT(p+(4dT−1)T), and BT(p+(4dT)dT).
Compute B2T(v)=BT(v+T)BT(v).
Each round spends O(m2dTlog(dT)) complexity on shifting. Each round performs only Θ(dT) matrix multiplication, whose complexity can be regarded as O(m3dT).
Finally, it is enough to reach T≥n/d.
The preceding −P0(n)1 factor can be handled similarly.
Thus the preprocessing complexity is Θ(nd(m3+m2log(nd))).
For a query, we need only Θ(n/T) vector-matrix multiplications and O(T) brute-force transitions.
This part is clearly not the complexity bottleneck.
Therefore, the total complexity of the algorithm is Θ(nd(m3+m2log(nd))).
When coding, cyclic convolution can be used to reduce the constant factor of the NTT.
In applications, we often extract a distant coefficient of a known D-finite GF, so m,d are all constants; this gives distant-coefficient evaluation in Θ(nlogn).
References
Alin Bostan, Pierrick Gaudry, and Eric Schost. Linear recurrences with polynomial coefficients and application to integer factorization and Cartier–Manin operator.