定义
给定 n 个点 (xi,yi) 满足 xi=xj(i=j),它们能唯一确定一个 n−1 次的多项式 f(x):
f(x)=i=1∑nyij=i∏xi−xjx−xj
容易验证,带入 f(xk),当 i=k 时,后面的那个乘积总会有 0;当 i=k 时,后面的乘积为 1,并且这个多项式是 n−1 次的。
[LGP5667] 拉格朗日插值2
这个题目相较于模板题更为常见,给定的 xi=i。
设 hi=f(m+i),数据范围保证了 m>n,要求的是 h0∼hn。
列式子:
hk=i=0∑nyij=i∏i−jm+k−j=(m+k)n+1i=0∑ni!(n−i)!(m+k−i)(−1)n−iyi=(m+k)n+1i=0∑nm+k−ifi
其中 fi=i!(n−i)!(−1)n−iyi,这是可以 O(n) 预处理出来的。
观察这个形式,我们希望右边是卷积 ∑i=0kfigk−i 的样子,但是这个求和是到 n,所以我们需要进行一步转化。
具体地说,令 gn+k−i=m+k−i1,则 gi=m−n+i1,就有:
hk=(m+k)n+1i=0∑n+kfign+k−i
当 i>n 时,fi=0,所以这和原式是等价的。
于是,我们只要预处理出 f,g 数组,做卷积 c=f∗g,就有 hk=(m+k)n+1cn+k,前面的下降幂维护一个窗口即可。
AC Code。
[CF622F] The Sum of the k-th Powers
首先 S(x)=∑i=1xik 是一个 k+1 次的多项式,于是我们可以根据 (j,∑i=0jik) 令 j=0∼k+1 即可插值出这样一个多项式 S(x)。
我们只需要求 S(n) 这个点处的值,当 n≤k+1 时我们直接把预处理的信息输出即可,当 n>k+1 时我们带入公式:
Sn=i=0∑k+1Sii=j∏i−jn−j=i=0∑k+1Sii!(k+1−i)!(−1)k+1−i(n−i)nk+2=nk+2i=0∑k+1i!(k+1−i)!(−1)k+1−i(n−i)Si
直接 O(klogP) 做即可,其中 P 是模数。
AC Code。
[ICPC2019 Nanchang Inventional] Polynomial
首先我们要清楚,对于 S(x)=∑i=0xf(i) 是一个 n+1 次的多项式,所以我们可以通过 (j,S(j)) 其中 j=0∼n+1 来唯一地确定这个多项式。
因此我们可以通过一次拉格朗日插值求出 f(n+1),然后对 f 求前缀和即可得到 S0∼Sn+1。
对于每次询问,求 SR−SL−1 即可,复杂度为 O(TmnlogP),其中 P 是模数。
AC Code。
[ICPC2021 Brazil Subregional] Assigning Prizes
设 dp(i,j) 表示 xi=j 时,i∼n 的方案数。
转移显然有 dp(i,j)=∑k=pi+1jdp(i+1,k)=S(i+1,j)−S(i+1,pi+1−1),并且当 S(n,j)=j−pn+1(j≥pn)。
注意,这里 pi←maxj=inpj,我们希望当 j<pi 时, dp(i,j)=0。
观察这个关系,我们可以看出,S(n,x) 是一条直线,而 S(n−1,x) 是连续的 S(n,y) 的和,所以它是一个二次的曲线,以此类推,可以推出 S(i,x) 能确定一个 n−i+1 次的多项式。
然而,如果你直接这样做,是无论如何也无法维护好 dp 和 S 的关系的,因为前后位置的下标对应都不一样。
因此,由于 (pi,S(i,pi))∼(R,S(i,R)) 这些点在一个 n−i+1 次的多项式上,我们令 (0,S(i,0))∼(pi−1,S(i,pi−1)) 也在这个多项式上。
拓展完定义后我们需要保证当题目数据给出 p1>R 时,程序输出 0,这里需要特判。
那么对于 S(i,x) 这个多项式,我们可以先根据文章一开头给出的递推式计算出 dp(i,x)。由于 S(i+1,x) 是一个 n−i 次的多项式,那么连续的和就是一个 n−i+1 次的多项式。
对于 ∏j=0i−1(x−j)∏j=i+1deg(x−j) 我们需要预处理前缀后缀积,让拉格朗日插值的复杂度单次为 O(n)。上面题目并没有卡 logP 的做法,这个题目卡了,所以最终的复杂度为 O(n2)。
AC Code。