zoukankan      html  css  js  c++  java
  • 拉格朗日插值法

    题目描述

    由小学知识得(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))

    代入柿子

    [egin{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) = egin{cases} 1~~~(i = j)\ 0~~~(i eq 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 eq i}^{jleq 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 eq i}^{jleq n}frac{x_k - x_j}{x_i - x_j} ]

    考虑 (O(1)) 求出 (prod_{j eq 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_ifrac{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_iprod_{i eq j} frac{x - x_j}{x_i - x_j}\ ~~\ = sum_{i = 1}^{n}y_ifrac{prod_{i eq j}{x - x_j}}{prod_{i eq j}{x_i - x_j}}\ ~~\ = sum_{i = 1}^{n}y_ifrac{prod_{i = 1}^{n}(x - x_i)}{prod_{i eq j}(x_i - x_j)*(x - x_i)} ~~\ ~=prod_{i = 1}^{n}(x - x_i)sum_{i = 1}^{n}frac{y_i}{prod_{i eq j}(x_i - x_j)*(x - x_i)} ]

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

    然后柿子就成了

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

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

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

    预处理出逆元

    时间复杂度 (O(n))

    参考资料

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

    拉格朗日插值学习小结

    拉格朗日插值学习总结

  • 相关阅读:
    CF980E The Number Games
    UVALive 2995 Image Is Everything
    CF1148F Foo Fighters
    CF22E Scheme
    CF1045G AI robots
    学习笔记 并查集维护区间删除
    HEOI 十二省联考退役记
    立方网面试题总结
    Django学习排错备注
    追求卓越之旅(转)
  • 原文地址:https://www.cnblogs.com/Arielzz/p/14940509.html
Copyright © 2011-2022 走看看