Lagrange 插值
补知识点。
多项式的点值表示法与系数表示法
这个应该很容易理解。
多项式的系数表示法就是 f(x)=∑i=0naixi,这可以决定一个 n 次多项式,多项式“次数”的定义也来源于此。
多项式的点值表示法是给出 n+1 个多项式所经过的点 (xi,yi),满足 xi 两两互不相同,可以确定一个 n 次多项式。
Proof:
考虑列方程:∀k∈[0,n],∑i=0naixki=yk,把 a 看作变量,考虑这个方程组的系数矩阵:
111⋮1x0x1x2⋮xnx02x12x22⋮xn2⋯⋯⋯⋱⋯x0nx1nx2n⋮xnn
由于 xk 两两不同,故该矩阵的各行向量线性无关,ai 有唯一解,类似的可证它无法确定一个更高次多项式。
上述矩阵也被称为这个点值表示法的 范德蒙德矩阵。
插值就是点值表示法转化成系数表示法的过程。
朴素的插值算法正如刚刚所见,对范德蒙德矩阵高斯消元即可。
Lagrange 插值
任意情况插值
我们发现套用定义解决这个问题实在是太笨蛋了,有没有什么更优秀的做法呢?
Lagrange 插值做的事情类似 CRT,对每个 i∈[0,n],求出一个多项式 fi 使得 fi(xj)=[i=j]yi,那么 f=∑ifi,根据上面的论证我们可以知道必定存在这样 n 个多项式。
由于 ∀i=j,fi(xj)=0,所以 fi 的分解因式中必定含有 (x−xj) 这一项。
而我们又要保证 fi(xi)=yi,我们可以对 ∏j=i(x−xj) 的结果微调,使得其最后等于 yi,简单的构造我们得到了 Lagrange 插值公式:
fi(x)=yij=i∏xi−xjx−xjf(x)=i∑yij=i∏xi−xjx−xj
在计算上,我们可以暴力求出 ∏j(x−xj),然后对于每一个 i 暴力多项式除法除掉 (x−xi),最后对每个 i 乘上 yi∏j=i(xi−xj)−1,然后把所有多项式加起来即可。
预处理逆元,我们得到一个 O(n2) 的算法。
多项式科技已经可以实现 O(nlog2n) 的快速插值,但那超出了我的能力范围。
连续取值插单点值
对于更常见的情况,例如我们想暴力求矩阵的特征多项式 det(xI−A),我们是可以自由选择若干 x 代入的,而此时如果我们选择了 xi=i,我们的插值可以变得更为迅速:
f(x)=i∑yij=i∏i−jx−j
你可能会疑惑:这用多项式运算不还是 O(n2) 的吗。
的确如此,但如果我们的所求只是某个点的值,情况就不一样了。
f(k)=i∑yij=i∏i−jk−j
把 ∏ 中的分子分母分开考虑,预处理出 pj=∏i=0j−1(k−i),sk=∏i=j+1n(k−i),则分子为 pisi。
分母不考虑符号的话是两个阶乘拼起来,考虑一下符号变成最终的式子:
f(n)=i∑yi(−1)n−ifacifacn−ipisi
预处理阶乘的逆元,复杂度 O(n)。
其实我们如果不是带着强烈的求多项式系数的目的求出多项式,而只是为了求出一个多项式用于代入计算,那么连续点值 Lagrange 插值计算和代入多项式计算二者的复杂度并无区别,所以点值表示法作为一种表示法,做基本的求一个点处值还是很轻松的。
大多数题不会难为你让你求系数表示法的,真求了就变成 OGF 大混战。
本题也是求单点值。
求 ∑i=0nik,n≤109,k≤106。
考虑到 k 很小,我们可以将 ∑i=0nik 视作一个关于 n 的 k+1 次多项式 f(n),求其前 O(k) 项都是简单的,暴力累加即可。
然后插值。
参考资料
多项式 I:拉格朗日插值与快速傅里叶变换