拉格朗日插值小记

对于 \(n\) 个点 \((x_i,y_i)\)\(x_i\) 互不相同,则我们可以 唯一 确定一个 \(n-1\) 次多项式经过这 \(n\) 点。

1. 拉格朗日插值

拉格朗日插值的核心思想是每次只考虑一个点值,将其他点值都视作 \(0\),即对于每一个点 \((x_i,y_i)\),我们构造一个函数 \(f_i(x)\)

  • 当且仅当 \(x = x_i\)\(f_i(x) = y_i\),当 \(x = x_j(j \not = i)\) 时,\(f_i(x) = 0\)

这样我们可以构造出经过所有点的函数 \(f(x) = \sum f_i(x)\)

则我们首先对于每个点 \((x_i,y_i)\),设 \(f_i(x) = \prod\limits_{j \not = i}(x - x_j)\),则显然可以满足上述条件,而我们又要满足 \(f(x_i) = y_i\),则我们可以构造:

\[f(x) = \sum\limits_{i=1}^n y_i \prod\limits_{i \not = j} {\dfrac {x - x_j} {x_i - x_j}} \]

这样我们可以轻松的用 \(\mathcal{O}(n^2)\) 的复杂度解决。

P4781 【模板】拉格朗日插值

直接套式子即可,逆元可以乘完再逆,写的时候脑子宕机了。

int main(){
	n = read(),k = read();
	for(int i = 1;i <= n;i++)x[i] = read(),y[i] = read();
	ll ans = 0;
	for(int i = 1;i <= n;i++){
		ll s = y[i] % mod;
		for(int j = 1;j <= n;j++){
			if(i == j)continue;
			s = s * (k - x[j] + mod) % mod;
			s = s * ksm((x[i] - x[j] + mod) % mod,mod - 2) % mod;
		}
		(ans += s) %= mod;
	}
	printf("%lld\n",ans);

	return 0;

}

2. 一些小优化

当这些点值是 \((i,y_i)\) 时,则我们可以分开处理 \(\prod\limits_{i \not = j}x - j\)\(\prod\limits_{i \not = j}i - j\)

前者我们可以首先算出 \(\prod \limits x - j\),求的时候除个 \((x - i)\) 即可。

后者我们可以分成 \(j < i\)\(j > i\) 两个部分,求出答案是 \((i-1)! \times (n-i)! (-1)^{n-i}\)

预处理逆元,复杂度 \(\mathcal{O}(n\log{V})\)

例题: CF622F The Sum of the k-th Powers

即求 \(\sum\limits_{i=1}^n i^k\)

\(n\) 太大,我们考虑关于 \(k\) 的复杂度。

首先我们可以知道这是一个关于 \(n\)\(k+1\) 次多项式,我们只需要暴力求出前 \(k+2\),即可拉插,复杂度 \(\mathcal{O}(n\log{V})\)

  • 如何证明是一个 \(k+1\) 次多项式呢?

    我们可以归纳证明: 首先懒得奠基。

    假设该结论对所有 \(k < m\) 都成立,则现在证明 \(k = m\) 时成立。

    首先有 \((i+1)^{m + 1} - i^{m + 1} = \sum\limits_{j=0}^m\dbinom {m+1} j i^j\)

    我们对所有的 \(i\) 求和,左边是个裂项,答案为 \((n+1)^{m+1} - 1\)

    有 $$(n + 1)^{m+1} - 1 = \sum_{i=1}^{n} \sum_{j=0}^m \dbinom {m+1} j i^j = \sum_{j=0}^m\dbinom {m+1} j \sum_{i=1}^n i^j$$

    把右边 \(j = m\) 移项得 $$\sum_{i=1}^{n} i^m = (n + 1)^{m+1} - 1 - \sum_{j=0}^{m-1}\dbinom {m+1} j \sum_{i=1}^n i^j$$

    左半部分次数为 \(m + 1\),右半部分最大次数为 \(m - 1 + 1 = m\),证毕。

3. 多项式快速插值

不会

4. 例题

I CF622F The Sum of the k-th Powers

上述。
代码

II P4463 [集训队互测 2012] calc

首先我们考虑 DP,不妨设 \(a_i < a_{i+1}\),这样我们最后乘个 \(n!\) 即可。

\(f_{i,j}\) 表示值域为 \([1,i]\) 且序列长度为 \(j\) 时的答案。

则有转移方程 \(f_{i,j} = f_{i-1,j} + f_{i-1,j-1} \times i\),直接写复杂度是 \(\mathcal{O}(kn)\) 的,无法通过。

我们可以发现 \(f_{i,j}\) 可以视为 一个关于 \(i\) 的比较小次数的多项式,我们考虑分析一下其次数。

  • 由转移方程得,\(f_{i,j} - f_{i-1,j} = f_{i-1,j-1} \times i\)

    首先有对于一个 \(k\) 次多项式 \(f(x)\),则 \(f(x+1) - f(x)\) 是一个 \(k-1\) 次多项式,可以二次项定理拆开简单证明。

    \(f_{i,j}\) 的次数 \(-1\) 等于 \(f_{i,j-1}\) 的次数 \(+1\),又有 \(f_{i,0}\) 是一个 \(0\) 次多项式,可得 \(f_{i,j}\) 是一个关于 \(i\)\(2j\) 次多项式。

则我们求出前 \(2n+1\) 个 DP 值,拉插一下即可。

复杂度 \(\mathcal{O}(n^2)\)

代码

III BZOJ3453: tyvj 1858 XLkxc

题意,给定 \(k,n,d,a\)\(k \leq 123\)\(n,d,a \leq 123456789\),求 $$\sum_{i=0}^{n} \sum_{j=1}^{a+id} \sum_{p=1}^{j} p^k$$

首先 \(f(x) = \sum\limits_{i=1}^{x}i^k\) 是一个 \(k+1\) 多项式,则 \(g(x) = \sum\limits_{i=1}^{x}f_i\) 是一个 \(k+2\) 次多项式,都可以 拉插 求出。

最后答案即为 \(\sum\limits_{i=0}^{n}g(a+id)\),答案最多是一个关于 \(n\)\(k+3\) 次多项式,也可以 拉插,可以求出前 \(k+4\) 项,其中 \(g(x)\) 在内部也可以拉插求,总复杂度 \(\mathcal{O}(k^3)\),利用 2. 的技巧可以优化到 \(\mathcal{O}(k^2)\)

没有代码。

参考文章

只是 Lagrange 插值 - Hagasei-Chan

posted @ 2024-10-03 18:35  oXUo  阅读(85)  评论(0)    收藏  举报
网站统计