[学习笔记]拉格朗日插值

其实是复习,但基本上等同于学习(大雾)。

理论推导

基本公式

构造一个合法的函数 f ( x ) f(x) f(x),使得该函数过 n + 1 n+1 n+1个点 ( x i , y i ) (x_i,y_i) (xi,yi),且函数次数不超过 n n n

我们先直接看这个构造出来的函数:
f ( k ) = ∑ i = 1 n y i ∏ i ≠ j k − x j x i − x j f(k)=\sum^{n}_{i=1} y_i\prod_{i≠j}\frac{k-x_j}{x_i-x_j} f(k)=i=1nyii=jxixjkxj
将每个 ( x i , y i ) (x_i,y_i) (xi,yi)带入公式就会发现这个函数神奇的含义:

  • k = x p k=x_p k=xp,那么对于 i ≠ p i≠p i=p,后面连乘的部分答案一定为 0 0 0, i = p i=p i=p时答案为 1 1 1。因此最终结果 f ( k ) = y p f(k)=y_p f(k)=yp

因此这个多项式完美的符合问题的要求,由于 n + 1 n+1 n+1一个点能够唯一确定一个 n n n次多项式,因此我们用构造的方法成功解决了这个问题。

重心拉格朗日插值

简单来说就是我们把式子变一下形,令 w i = 1 ∏ i ≠ j n ( x i − x j ) w_i=\frac{1}{\prod^n_{i≠j}(x_i-x_j)} wi=i=jn(xixj)1
因此:
F ( x ) = ∏ i = 0 n ( x − x i ) × ∑ j = 0 n y j w i x − x j F(x)=\prod^n_{i=0}(x-x_i)\times \sum^{n}_{j=0}y_j\frac{w_i}{x-x_j} F(x)=i=0n(xxi)×j=0nyjxxjwi
每次增加一个数时,我们每次将每个 w i w_i wi多除以一个 ( x i − x n + 1 ) (x_i-x_{n+1}) (xixn+1)即可。
这样动态增加数就是单次 O ( n ) O(n) O(n)的了。
UPD:
在实际解决的问题中,我们很有可能遇到 x x x模意义下等于某一个 x j x_j xj导致分子为零的情况。
因此我们定义 p r e i = ∏ j = 0 i − 1 ( x − x j ) , s u f i = ∏ j = i + 1 n ( x − x j ) pre_i=\prod^{i-1}_{j=0}(x-x_j),suf_i=\prod^{n}_{j=i+1}(x-x_j) prei=j=0i1(xxj),sufi=j=i+1n(xxj)
原式变为
F ( x ) = ∑ j = 0 n y j ⋅ p r e i ⋅ s u f i ⋅ w i F(x)=\sum^n_{j=0}y_j·pre_i·suf_i·w_i F(x)=j=0nyjpreisufiwi

x x x取值连续时的拉格朗日插值I

给定一个不超过 n n n 次的多项式的 n + 1 n+1 n+1 个点值 f ( 0 ) , f ( 1 ) … f ( n ) f(0),f(1) \dots f(n) f(0),f(1)f(n),和一个正整数 m m m,求 f ( m ) f(m) f(m)

事实上,多数题目的 x x x取值都可以是连续的,此时我们可以利用一些特性来优化插值的过程。
例如上面的问题,我们代换一下公式:
f ( x ) = ∑ i = 0 n y i ∏ i ≠ j x − j i − j f(x)=\sum^n_{i=0}y_i \prod_{i≠j}\frac{x-j}{i-j} f(x)=i=0nyii=jijxj
除式下面的部分可以观察得到 ( − 1 ) m − i i ! ( m − i ) ! (-1)^{m-i}i!(m-i)! (1)mii!(mi)!,上面的部分显然可以使用阶乘表示,得到:
f ( x ) = x ! ( x − n − 1 ) ! ∑ i = 0 n ( − 1 ) n − i y i i ! ( n − i ) ! × 1 x − j f(x)=\frac{x!}{(x-n-1)!}\sum^n_{i=0}\frac{(-1)^{n-i}y_i}{i!(n-i)!}\times \frac{1}{x-j} f(x)=(xn1)!x!i=0ni!(ni)!(1)niyi×xj1
UPD: 如果需要处理分母为零的情况,用重心拉个朗日插值的解决方法同样解决即可。

x x x取值连续时的拉格朗日插值II

给定一个不超过 n n n 次的多项式的 n + 1 n+1 n+1 个点值 f ( 0 ) , f ( 1 ) … f ( n ) f(0),f(1) \dots f(n) f(0),f(1)f(n),和一个正整数 m m m,求 f ( m ) , f ( m + 1 ) , … f ( m + n ) f(m),f(m+1),\dots f(m+n) f(m),f(m+1),f(m+n)

其实想法挺巧妙的,我好像没见过这个套路
由于 x x x连续,我们套用上面的公式:
f ( x + k ) = ( x + k ) ! ( x + k − n − 1 ) ! ∑ i = 0 n ( − 1 ) n − i y i i ! ( n − i ) ! × 1 x + k − j f(x+k)=\frac{(x+k)!}{(x+k-n-1)!}\sum^n_{i=0}\frac{(-1)^{n-i}y_i}{i!(n-i)!}\times \frac{1}{x+k-j} f(x+k)=(x+kn1)!(x+k)!i=0ni!(ni)!(1)niyi×x+kj1
看起来很像卷积:
A ( x ) = ∑ i = 0 n ( − 1 ) n − i y i i ! ( n − i ) ! , B ( x ) = ∑ i = 0 n 1 x + k − j A(x)=\sum^n_{i=0}\frac{(-1)^{n-i}y_i}{i!(n-i)!},B(x)=\sum^n_{i=0}\frac{1}{x+k-j} A(x)=i=0ni!(ni)!(1)niyi,B(x)=i=0nx+kj1
然而 B ( x ) B(x) B(x)里面有 k k k,不能直接做。
但是注意到相邻两个点值表示的多项式等价于每次向左平移一位。
因此我们重新定义 B ( x ) = ∑ i = 0 2 n 1 x + i − n B(x)=\sum^{2n}_{i=0}\frac{1}{x+i-n} B(x)=i=02nx+in1
此时 A ( x ) ⋅ B ( x ) A(x)·B(x) A(x)B(x)的第 [ n , 2 n ] [n,2n] [n,2n]项分别对应的就是 f ( x + k ) f(x+k) f(x+k)
画一下图就知道为什么了。

实现细节:因为 m m m有一点大所以预处理阶乘很麻烦…

例题

拉格朗日插值法的最大难点其实在于对多项式次数的分析。
然而实践证明多拿几个点来插值也没有什么问题。

P4463 [集训队互测2012] calc

离散拉格朗日插值基础dp题。
定义dp_{i,j}表示 i i i个数,每个数在 [ 1 , j ] [1,j] [1,j]的范围内的方案数。
首先写出dp式, f i , j = f i − 1 , j − 1 × i × j + f i , j − 1 f_{i,j}=f_{i-1,j-1}\times i\times j+f_{i,j-1} fi,j=fi1,j1×i×j+fi,j1
然后我们证明 f ( i ) f(i) f(i)是一个 2 i 2i 2i次的多项式。
f ( i ) f(i) f(i)多项式次数为 g i g_i gi
移项 f i , j − f i , j − 1 = f i − 1 , j − 1 × i × j f_{i,j}-f_{i,j-1}=f_{i-1,j-1}\times i\times j fi,jfi,j1=fi1,j1×i×j
左边是次数是 g i − 1 g_i-1 gi1的[ x d − ( x − 1 ) d x^d-(x-1)^d xd(x1)d没有 x d x^d xd项]。
因此 g i − 1 = g i − 1 + 1 g_i-1=g_{i-1}+1 gi1=gi1+1.
g i = 2 i g_i=2i gi=2i
然后带入 2 n + 1 2n+1 2n+1包括i=0)个点插值即可。
复杂度: O ( n 2 ) O(n^2) O(n2)

CF995F Cowmpany Cowmpensation

跟上一题没什么区别,写出dp式子然后分析多项式次数,同样插值即可。
复杂度: O ( n 2 ) O(n^2) O(n2)

[JLOI2016]成绩比较

我们可以尝试着用 d p dp dp来解决这个问题。
定义 f i , j f_{i,j} fi,j表示已经处理了前 i i i次考试成绩,现在有 j j j个人被B神碾压的方案数。
f i , j = ( ∑ k = j n f i − 1 , k ⋅ ( k j ) ⋅ ( n − k − 1 r i − 1 − ( k − j ) ) ) ∑ k = 1 u i k n − r i ⋅ ( u i − k ) r i − 1 f_{i,j}=\bigg( \sum^n_{k=j} f_{i-1,k}·\binom{k}{j}·\binom{n-k-1}{r_i-1-(k-j)} \bigg)\sum^{u_i}_{k=1} k^{n-r_i}·(u_i-k)^{r_i-1} fi,j=(k=jnfi1,k(jk)(ri1(kj)nk1))k=1uiknri(uik)ri1
看上去一切顺利,但是 u i u_i ui的范围是 1 0 9 10^9 109,直接处理显然会T。
我们设这个部分 f ( i ) = ∑ k = 1 u i k n − r i ⋅ ( u i − k ) r i − 1 f(i)=\sum^{u_i}_{k=1} k^{n-r_i}·(u_i-k)^{r_i-1} f(i)=k=1uiknri(uik)ri1
和式里面是一个 n − 1 n-1 n1次的多项式(关于 u i u_i ui)。
那么求和就变成了一个 n n n次多项式。
插值求出每个 f ( i ) f(i) f(i)即可。
复杂度: O ( n 3 log ⁡ n ) O(n^3\log n) O(n3logn)(搞了个快速幂…)。

[2018 集训队互测]小 H 爱染色

[NOI2019] 机器人

这种题目口胡起来还是很愉快的…
首先我们很容易得到一个 50 50 50分的dp。
定义 d p [ l ] [ r ] [ v ] dp[l][r][v] dp[l][r][v] [ l , r ] [l,r] [l,r]中最大值不差过 v v v的方案数。
那么有 d p [ l ] [ r ] [ v ] = ∑ m i d ∑ k d p [ l ] [ m i d − 1 ] [ k ] × d p [ m i d + 1 ] [ r ] [ k − 1 ] dp[l][r][v]=\sum_{mid}\sum_{k}dp[l][mid-1][k]\times dp[mid+1][r][k-1] dp[l][r][v]=midkdp[l][mid1][k]×dp[mid+1][r][k1]
然后有一个结论:将给出的区间一起离散化,每相邻两点的一个区间是一个 n n n次的多项式。
有了这个结论了之后我们对每个段只取前 n n n个值进行dp,接下来的我们可以直接通过插值插出来。
这样可以得到95分的好成绩。
如果要得到满分的话我们需要将每层一定用不到的dp值域舍去(因为对于区间比较短的dp数组, k k k比较大的状态其实是和 d p [ 1 ] [ n ] [ p − p + n − 1 ] dp[1][n][p-p+n-1] dp[1][n][pp+n1]无关的)。

「from CommonAnts」一道数学题 加强版

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值