解题报告多项式求值与插值(拉格朗日插值)(ACM / OI)

Posted 繁凡さん

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解题报告多项式求值与插值(拉格朗日插值)(ACM / OI)相关的知识,希望对你有一定的参考价值。

整理的算法模板合集: ACM模板

点我看算法全家桶系列!!!

实际上是一个全新的精炼模板整合计划


繁凡出品的全新系列:解题报告系列 —— 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数( 1 ∼ 5 1 \\sim 5 15),以模板题难度 1 1 1 为基准。


这样大家在学习算法的时候就可以执行这样的流程:

%
阅读【学习笔记】 / 【算法全家桶】学习算法 ⇒ \\Rightarrow 阅读相应算法的【解题报告】获得高质量题单 ⇒ \\Rightarrow 根据一句话题解的提示尝试自己解决问题 ⇒ \\Rightarrow 点开详细题解链接学习巩固(好耶)
%
要是26个英文字母用完了我就接上24个希腊字母,我就不信50道题不够我刷的hhh

%
解题报告系列合集:【解题报告系列】超高质量题单 + 题解(ICPC / CCPC / NOIP / NOI / CF / AT / NC / P / BZOJ)

本题单前置知识:【学习笔记】多项式全家桶(包含全套证明)

拉格朗日插值法

在这里插入图片描述
有拉格朗日插值公式:

f ( x ) = ∑ i = 1 n y i ∏ j ≠ i x − x j x i − x j f(x)=\\sum_{i=1}^ny_i\\prod_{j\\neq i}\\dfrac {x-x_j} {x_i-x_j} f(x)=i=1nyij=ixixjxxj

A. P4781 【模板】拉格朗日插值

Weblink

https://www.luogu.com.cn/problem/P4781

Problem

在这里插入图片描述

我们将 n n n个点带入拉格朗日插值公式计算 f ( k ) f(k) f(k) 即可。时间复杂度 O ( n 2 ) O(n^2) O(n2)

注意本题还要求逆元,为了防止求逆元的时间复杂度影响整体的时间复杂度,所以我们分别计算出分子和分母,再将分子乘进分母的逆元,累加进最后的答案,时间复杂度的瓶颈就不会在求逆元上,总体的时间复杂度为 O ( n 2 ) O(n^2) O(n2)

Code

本题需要累乘,会爆int,记得开long long

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 500007;
typedef long long ll;
const int mod = 998244353;
ll n, m, k;

struct Point
{
    ll x, y;
}A[N];

ll qpow(ll a, ll b, ll c)
{
    ll res = 1;
    while(b) {
        if(b & 1) res = res * a % c;
        a = a * a % c;
        b >>= 1;
    }
    return res;
}

ll inv(ll x) {return qpow(x, mod - 2, mod);}

int main()
{
    scanf("%lld%lld", &n, &k);
    for(int i = 1; i <= n; ++ i) {
        scanf("%lld%lld", &A[i].x, &A[i].y);
    }
    ll ans = 0;

    for(int i = 1; i <= n; ++ i) {
        ll s1 = A[i].y % mod;
        ll s2 = 1ll;
        for(int j = 1; j <= n; ++ j) {
            if(i != j) {
                s1 = s1 * (k - A[j].x) % mod;
                s2 = s2 * (A[i].x - A[j].x) % mod;
            }
        }
        ans += s1 * inv(s2) % mod;
    }
    printf("%lld\\n", (ans % mod + mod) % mod);
    return 0;
}

我们使用拉格朗日插值公式,对于一个数 k k k ,我们很容易在 O ( n 2 ) O(n^2) O(n2) 时间求得 F ( k ) F(k) F(k) 的数值,如果 x i x_i xi 是连续的,我们甚至可以利用预处理在 O ( n ) O(n) O(n) 时间内得到 F ( k ) F(k) F(k) 的数值。
但是如果 x i x_i xi 不连续,又有多组查询,就需要得到这个多项式的系数以保证求一个函数值的时间为 O ( n ) O(n) O(n)
在这里插入图片描述

重心拉格朗日插值法

考虑对拉格朗日插值公式进行优化:

f ( x ) = ∑ i = 1 n y i ∏ j ≠ i x − x j x i − x j f(x)=\\sum_{i=1}^n y_i\\prod_{j\\neq i}\\dfrac {x-x_j} {x_i-x_j} f(x)=i=1nyij=ixixjxxj

h = ∏ i = 1 n x − x i h=\\prod_{i=1}^n x-x_i h=i=1nxxi
带入得:
= h ∑ i = 1 n ∏ j ≠ i y i ( x i − x j ) ( x − x i ) =h\\sum_{i=1}^n \\prod_{j\\neq i}\\dfrac {y_i} {(x_i-x_j)(x-x_i)} =hi=1nj=i(xixj)(xxi)yi


t i = ∏ j ≠ i y i x i − x j t_i=\\prod_{j\\neq i} \\dfrac {y_i} {x_i-x_j} ti=j=ixixjyi

带入得:

= h ∑ i = 1 n t i x − x i =h\\sum_{i=1}^n \\dfrac {t_i} {x-x_i} =hi=1nxxiti

在每次加入一个新点时,计算出它的 t i t_i ti ,并且更新别的点的 t i t_i ti ,时间复杂度 O ( n ) O(n) O(n),加

以上是关于解题报告多项式求值与插值(拉格朗日插值)(ACM / OI)的主要内容,如果未能解决你的问题,请参考以下文章

拉格朗日插值法

拉格朗日插值方法

拉格朗日插值公式

拉格朗日插值法理论误差怎么得的

多项式快速插值

拉格朗日插值法(图文详解)