拉格朗日插值学习笔记

拉格朗日插值

第一步:子函数 \(f_i(x)=\begin{cases}1&x=x_i\\0&x=x_j(i\ne j)\end{cases}\)

由此可得:\(f(x)=\sum\limits_{i=1}^ny_if_i(x)\)

第二步:对于 \(f_i(x)\),要满足当\(x=x_i\)时,\(y=1\),而\(x\ne x_i\)时,\(y=0\)故:

\(f_i(x)=\dfrac{\prod\limits_{j=1,j\ne i}^n(x-x_j)}{\prod\limits_{j=1,j\ne i}^n(x_i-x_j)}\)

这就是拉格朗日基本多项式(插值基函数)

因此多项式第\(i\)项为 \(y_i\times\dfrac{\prod\limits_{j=1,j\ne i}^n(x-x_j)}{\prod\limits_{j=1,j\ne i}^n(x_i-x_j)}\)

所以又可以把多项式写为:

\(f(x)=\sum\limits_{i=1}^ny_i\times\dfrac{\prod\limits_{j=1,j\ne i}^n(x-x_j)}{\prod\limits_{j=1,j\ne i}^n(x_i-x_j)}\)

展开后为:\(f(x)=\dfrac{y_1(x-x_2)(x-x_3)\cdots(x-x_n)}{(x_1-x_2)(x_1-x_3)\cdots(x_1-x_n)}+\dfrac{y_2(x-x_1)(x-x_3)\cdots(x-x_n)}{(x_2-x_1)(x_2-x_3)\cdots(x_2-x_n)}\cdots+\dfrac{y_n(x-x_1)(x-x_2)\cdots(x-x_{n-1})}{(x_n-x_1)(x_n-x_1)\cdots(x_n-x_{n-1})}\)

我们可以发现,当\(x=x_i\)时,除了第\(i\)项,其余项的分子中都有一项为\((x-x_i)\),故其余项都为0,而对于第\(i\)项,分子中的\((x-x_j)(j\ne i)\)与分母中的\((x_i-x_j)(j\ne i)\)消掉了,最终只剩下了分子中的\(y_i\),因此就证明了\(f(x)\)就是满足\(f(x_i)=y_i\)的多项式。

1.P3643 [APIO2016] 划艇

题意:有\(n\)个位置,每个位置上可以选一个在\([l_i,r_i]\)中间的数,并且要大于它前面任意一个选了的数,也可以不选,求方案数。

思路:先考虑朴素DP。设\(f[i][j]\)表示第\(i\)个位置选了\(j\)的方案数,那么

\[f[i][j]=f[i-1][j]+\sum\limits_{k=1}^{j-1}f[i-1][k] \]

我们发现如果把第二维\(j\)看作自变量的话,那么可以发现这是一个多项式,而每求一次前缀和次数+1,所以最高是\(n\)次多项式,那么我们带入\(n+1\)个点值进去就可以得到答案。

复杂度\(O(n^3)\)

2.P8290 [省选联考 2022] 填树

题意:给一棵树,每个点的点权要么是 0,要么是 \([l_x,r_x]\) 中的数,你要选择一条链,让这条链上的点权不为 0,求所有可能的满足非 0 极差不超过 \(k\) 的方案数和权值和。

思路:首先考虑朴素的暴力。我们枚举所有点权所在的区间 \([l,l+k]\),然后计算答案,因为要取到下界,就要容斥掉 \([l+1,l+k]\) 的答案。求答案的过程可以用树形 DP,每个点能选的是一个区间,那么可以算出当前点为链头和为 LCA 的答案,于是就可以做到 \(O(nV)\)

考虑优化。我们发现对于选择的区间 \([l,l+k]\),每个点能取的范围是一个一次函数,那么总的贡献就是由这些一次函数形成的次数为 \(n\) 的多项式,这就不难想到用拉格朗日插值,代入 \(n+2\) 个点值就可以求出答案。对于求权值和,每个点能选的权值和是一个二次函数,那么总共就是 \(2n+1\) 次多项式,也可以同样处理。

复杂度 \(O(n^3)\)

3.P7116 [NOIP2020] 微信步数

题意:在 \(k\) 维长方体中你规划了一个行进路线,循环往复,直到走出这 \(k\) 维长方体,才算走完。问以这 \(k\) 维长方体中的每一个位置为起点,你是否都能走完,如果能,输出你走的步数之和。

思路:先考虑能否走完。显然,每一维是独立的,如果有一维可以走完那么就会结束。如果在一轮中会走出去或者走完一轮后不在起点就会走完。

从这入手,可以把走路改成把边界往内缩,这样就可以有一个 \(O(nmT)\) 的做法,可以拿到 45 分。

因此,假设在第 \(T\) 轮结束,那么后 \(T-1\) 轮都是一样的,只有第一轮不一样。

对于一轮,假设第一轮后还活着 \(a_j\) 个位置,每轮会去掉 \(b_j\) 个位置,最后一轮的 \(i\) 步去掉 \(f_i=r_i'-l_i'\) 个位置,那么在第 \(x+2\) 轮的第 \(i\) 步时,还活着 \(a_j-xb_j-f_i\) 个点,贡献是 \(\prod(a_j-xb_j-f_i)\)

于是总贡献就是 \(\sum\limits_{i=1}^n\sum\limits_{x=0}^T\prod\limits_{j=1}^m(a_j-xb_j-f_i)\),内层就是一个关于 \(x\)\(m\) 次多项式,可以 \(O(m^2)\) 暴力求。那么现在的问题就是求 \(\sum\limits_{x=0}^Tx^k\),可以直接拉格朗日插值,于是就做完了。

复杂度 \(O(nm^2)\)

4.[ARC118F] Growth Rate

题意:给定一个整数 \(M\) 和一个序列 \(\{A_N\}\),计数值域为 \([1,M]\) 的序列个数 \(\{X_{N+1}\}\) 满足 \(\forall i\in[1,N] A_iX_i\leqslant X_{i+1}\),答案对 \(998244353\) 取模。

思路:插值好题。

首先有暴力 DP。设 f[i][j]$ 表示 \(x_i=j\) 的方案数,那么转移是 \(f[i][j]\leftarrow \sum\limits_{k\ge ja_i}f[i+1][k]\)

然后可以发现,对于每个 \(i\),有值的位置不多。具体地,记 \(lim_i\) 表示 \(f[i]\) 有值的位数,那么有 \(lim_{n+1}=M,lim[i]=\left\lfloor\dfrac{lim_{i+1}}{a_i}\right\rfloor\)

这样还是过不去。因为 \(j\) 这一维和值域相关,而且转移很简单,我们猜测 \(f[i][j]\) 是关于 \(j\) 的多项式。

\(g[i][j]=\sum f[i][j]\),那么有 \(f[i][j]=g[i+1][lim_{i+1}]-g[i+1][ja_i-1](j\le lim_i)\),可以证明 \(f[i][j]\) 是关于 \(j\)\(n-i+1\) 次多项式,\(g[i][j]\) 是关于 \(j\)\(n-i+2\) 次多项式。

因为我们维护的插值是连续的,可以线性计算,那么我们不需要维护系数,可以直接维护点值,然后每次转移时再求我们要的点值,这样复杂度是 \(O(n^3)\) 的多项式。

又因为 \(\prod a_i=M\)\(a_i\) 中不为 1 的项只有 \(O(\log M)\) 个,而我们只有在 \(a_i\ne 1\) 的时候才需要插值,\(a_i=1\) 的时候 \(ja_i-1\) 的值是可以直接查表的,因此复杂度就是 \(O(n^2\log M)\)

一些特殊问题在模小质数高次幂下的做法

loj#6894. 自然 为例。

我们发现,因为模数是 \(2^{64}\),因此答案在 \(n\) 比较大的时候应该是一个关于 \(n\) 的次数不高的多项式,于是可以考虑插值,次数可以设为 300 次。至于求逆元,把 2 提出来处理就可以了。

代码可以看 我的提交记录

posted @ 2024-02-11 21:56  Xttttr  阅读(42)  评论(0编辑  收藏  举报