线性插值

感觉我正在日益沦为一个搬运工...

线性插值是指这样一个问题:给定整数n,m,以及一个n次多项式f在0,1,2,…,n−1处的点值,即f(0),f(1),f(2),…,f(n−1),希望能在关于n的线性时间内求出f(m)。n≤106,m≤1018。

利用多项式多点插值并求一次点值可以做到O(nlog2⁡n),但显然是过不去的。

我们考虑多项式f的牛顿级数,设其为c,即:

∑i=0n−1fixi=∑i=0n−1ci(xi)

那么对于m=0,1,2,…,n−1,显然有:

f(m)=∑i=0n−1ci(mi)

注意到当i≥m时(mi)为0,于是修改求和上限:

f(m)=∑i=0mci(mi)

这就是经典的二项式反演的形式,于是我们就得到:

ci=∑j=0i(−1)i−j(ij)f(j)

进回带到求和上限为n−1的式中,于是有:

f(m)=∑i=0n−1((mi)∑j=0i(−1)i−j(ij)f(j))

套路一波,将对j的求和放到外面:

f(m)=∑j=0n−1(f(j)∑i=jn−1(−1)i−j(mi)(ij))

为了直观,我们用i替换i−j:

f(m)=∑j=0n−1(f(j)∑i=0n−1−j(−1)i(mi+j)(i+jj))

利用(mi+j)(i+jj)=(mj)(m−ji)进行替换,得到:

f(m)=∑j=0n−1(f(j)∑i=0n−1−j(−1)i(mj)(m−ji))

于是(mj)可以放到前面:

f(m)=∑j=0n−1(f(j)(mj)∑i=0n−1−j(−1)i(m−ji))

现在考虑求出下面的式子的封闭形式:

∑i=0n−1(−1)i(mi)

首先是应用上指标反转使(−1)i(mi)=(i−m−1i):

∑i=0n−1(i−m−1i)

考虑加入一个数(−m−1−1)=0:

(−m−1−1)+∑i=0n−1(i−m−1i)

裂项:

(−m−1−1)+(−m−10)+∑i=1n−1(i−m−1i)(−m0)+∑i=1n−1(i−m−1i)

一直重复,直到只剩下:

(n−m−1n−1)

再进行上指标反转:

(−1)n−1(m−1n−1)

于是原式终于可以简化为:

f(m)=∑j=0n−1(f(j)(mj)(−1)n−1−j(m−1−jn−1−j))

整理,得:

f(m)=∑i=0n−1(−1)n−1−i(mi)(m−1−in−1−i)f(i)

用阶乘展开组合数:

f(m)=∑i=0n−1(−1)n−1−im!i!(m−i)!(m−1−i)!(n−1−i)!(m−n)!f(i)

继续整理:

f(m)=mn―∑i=0n−1(−1)n−1−i(m−i)i!(n−1−i)!f(i)

于是就可以做了,m−i的逆元可以用与预处理阶乘逆元的类似方法做到线性。总复杂度是O(n)。

upd:被强大的姐姐打脸了...其实直接用拉格朗日插值公式即可推出和上面一样的东西...所以这篇文章只是想说数学真奇妙。