Loading

拉格朗日插值法

题目描述

由小学知识得\(n + 1\)\(x\) 坐标不同的点确定唯一的最高次为 \(n\) 次的多项式 \(y = f(n)\) 。现在给出 \(n + 1\) 个点,求出这些点构成的多项式在某一位置的取值

拉格朗日插值法

假设给出的曲线是个二次多项式

\[f(x) = ax^2 + bx + c \]

现在有三个已经确定的点 \((x_1, y_1)\)\((x_2, y_2)\) , \((x_3, y_3)\)

代入柿子

\[\begin{cases} f(x_1) = ax_1^2 + bx_1 + c\\ f(x_2) = ax_2^2 + bx_2 + c\\ f(x_3) = ax_3^2 + bx_3 +c \end{cases} \]

很显然可以用高斯消元求出 \(a,b,c\) , 时间复杂度 \(O(n^3)\)

但拉格朗日插值法只需要 \(n^2\)

神奇的构造:

我们需要构造三条曲线 \(f_1,f_2,f_3\)

  • 对于第一条曲线 \(f_1(x)\)

\(f_1(x_1) = 1, f_1(x_2) = f_1(x_3) = 0\)

  • 对于第二条曲线 \(f_2 (x)\)

\(f_2(x_2) = 1, f_2(x_1) = f_2(x_3) = 0\)

  • 对于第三条曲线 \(f_3(x)\)

\(f_3(x_3) = 1, f_3(x_1) = f_3(x_2) = 0\)

然后

  • \(y_1f_1(x)\) 就能保证在 \(x_1\) 处为 \(y_1\)\(x_2,x_3\) 处为取值为 0

  • \(y_2f_2(x)\) 就能保证在 \(x_2\) 处为 \(y_2\)\(x_1,x_3\) 处为取值为 0

  • \(y_3f_3(x)\) 就能保证在 \(x_3\) 处为 \(y_3\)\(x_1,x_2\) 处为取值为 0

再然后

\[f(x) = y_1f_1(x) + y_2f_2(x) + y_3f_3(x) \]

神奇 发现这三条曲线就求出了想要的那条曲线

推导

对于上面的三条曲线显然满足性质

\[f_i(x_j) = \begin{cases} 1~~~(i = j)\\ 0~~~(i \neq j) \end{cases} \]

然后构造出这么个柿子

\[f_1(x) = \frac{(x - x_2)(x - x_3)}{(x_1 - x_2)(x_1 - x_3)} \]

进一步推广

\[f_i(x) = \prod_{j \neq i}^{j\leq n}\frac{x - x_j}{x_i - x_j} \]

然后就有了

\[f(x) = \sum_{i = 1}^{i = n} y_i * f_i(x) \]

P4781 【模板】拉格朗日插值

code

x 取值连续时

当题目要用到的 x 取值是连续的,上面的柿子可以优化到 \(O(n)\)

先列出柿子

\[f(k) = \sum_{i = 1}^{i = n} y_i * \prod_{j \neq i}^{j\leq n}\frac{x_k - x_j}{x_i - x_j} \]

考虑 \(O(1)\) 求出 \(\prod_{j \neq i}\frac{x_k - x_j}{x_i - x_j}\)

维护 \(x_k\) 的前缀积和后缀积

\[pre_i = \prod_{j = 0}^{i} (x_k - x_j)\\ suf_i = \prod_{j = i}^{n} (x_k - x_j) \]

对于分母,就是个阶乘形式,柿子就成了

\[f(k) = \sum_{i = 0}^{n}y_i\frac{pre_{i - 1}*suf_{i + 1}}{fac_i * fac_{n - i}} \]

坑:当 \(n - i\) 为奇数的时候分母为负值

CF622F The Sum of the k-th Powers

code

重心拉格朗日插值法

毒瘤题目会随时增加或者减少差值点,这个时候曲线就会改变,上面的柿子就需要重新计算了,那么上面的复杂度就会退化成 \(n^3\) 于是就有了重心拉格朗日插值 (好像牛顿插值法也可以办到 = =)

还是前面的柿子

\[f(x) = \sum_{i = 1}^{n}y_i\prod_{i\neq j} \frac{x - x_j}{x_i - x_j}\\ ~~\\ = \sum_{i = 1}^{n}y_i\frac{\prod_{i\neq j}{x - x_j}}{\prod_{i\neq j}{x_i - x_j}}\\ ~~\\ = \sum_{i = 1}^{n}y_i\frac{\prod_{i = 1}^{n}(x - x_i)}{\prod_{i\neq j}(x_i - x_j)*(x - x_i)} ~~\\ ~=\prod_{i = 1}^{n}(x - x_i)\sum_{i = 1}^{n}\frac{y_i}{\prod_{i\neq j}(x_i - x_j)*(x - x_i)} \]

令 $g = \prod_{i = 1}^{n}(x - x_i),t(i) = \prod_{i\neq j}(x_i - x_j) $

然后柿子就成了

\[f(x) = g\sum^n_{i = 1}\frac{y_i}{(x - x_i)*t(i)} \]

对于每加入或减少一个点,可以只 \(O(n)\) 更新 \(t(i)\)

对于求值,可以 \(O(n)\) 求出 g,然后套公式就好了

预处理出逆元

时间复杂度 \(O(n)\)

参考资料

如何直观地理解拉格朗日插值法?

拉格朗日插值学习小结

拉格朗日插值学习总结

posted @ 2021-06-27 14:17  Dita  阅读(475)  评论(4编辑  收藏  举报