解题报告多项式求值与插值(拉格朗日插值)(ACM / OI)
Posted 繁凡さん
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解题报告多项式求值与插值(拉格朗日插值)(ACM / OI)相关的知识,希望对你有一定的参考价值。
整理的算法模板合集: ACM模板
实际上是一个全新的精炼模板整合计划
繁凡出品的全新系列:解题报告系列 —— 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数( 1 ∼ 5 1 \\sim 5 1∼5),以模板题难度 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=1∑nyij=i∏xi−xjx−xj
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=1∑nyij=i∏xi−xjx−xj
设
h
=
∏
i
=
1
n
x
−
x
i
h=\\prod_{i=1}^n x-x_i
h=i=1∏nx−xi
带入得:
=
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=1∑nj=i∏(xi−xj)(x−xi)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=i∏xi−xjyi
带入得:
=
h
∑
i
=
1
n
t
i
x
−
x
i
=h\\sum_{i=1}^n \\dfrac {t_i} {x-x_i}
=hi=1∑nx−xiti
在每次加入一个新点时,计算出它的 t i t_i ti ,并且更新别的点的 t i t_i ti ,时间复杂度 O ( n ) O(n) O(n),加
以上是关于解题报告多项式求值与插值(拉格朗日插值)(ACM / OI)的主要内容,如果未能解决你的问题,请参考以下文章