拉格朗日插值

拉格朗日插值

考虑这样一个问题:有 \(n + 1\) 个不同的点值 \((x_{0 \sim n} , y_{0 \sim n})\) ,求一个 \(n\) 次多项式,满足其经过上述 \(n + 1\) 个点。

一般性插值法

对于第 \(i\) 个点,考虑构造一个多项式 \(F_i(k) = \begin{cases} y_i & k = x_i \\ 0 & k \not = x_i \end{cases}\) ,则 \(G(k) = \sum_{i = 0}^n F_i(k)\) 即为所求。

考虑构造 \(F_i(k)= y_i \prod_{i \not = j} \dfrac{k - x_j}{x_i - x_j}\)

解释:不难发现,当 \(k = x_j \ (j \not = i)\) 时,分子的累乘肯定有一项为 \(0\) ;当 \(k = x_i\) 时,分子分母累乘后肯定都会被约掉。因此这个多项式是符合条件的。

于是得到:

\[G(k) = \sum_{i = 0}^n y_i \prod_{j \not = i} \dfrac{k - x_j}{x_i - x_j} \]

时间复杂度 \(O(n^2)\)

横坐标连续时的插值方法

\(x_i\) 替换为 \(i\) ,新的式子即为:

\[G(k) = \sum_{i = 0}^n y_i \prod_{i \not = j} \dfrac{k - j}{i - j} \]

考虑优化。不难得到分子等于:

\[\dfrac{\prod_{j = 0}^n (k - j)}{k - i} \]

分母等于:

\[(-1)^{n - i} (i - 1)! (n - i)! \]

于是得到:

\[G(k) = \sum_{i = 0}^n y_i \dfrac{\prod_{j = 0}^n (k - j)}{(k - i) (-1)^{n - i} (i - 1)! (n - i)!} \]

inline int query(int k) {
	pre[0] = 1;
	
	for (int i = 1; i <= n; ++i)
		pre[i] = 1ll * pre[i - 1] * dec(k, i) % Mod;
	
	suf[n + 1] = 1;
	
	for (int i = n; i; --i)
		suf[i] = 1ll * suf[i + 1] * dec(k, i) % Mod;
	
	int ans = 0;
	
	for (int i = 1; i <= n; ++i)
		ans = add(ans, 1ll * y[i] * pre[i - 1] % Mod * suf[i + 1] % Mod * sgn(n - i) % Mod * invfac[i - 1] % Mod * invfac[n - i] % Mod);
	
	return ans;
}

重心拉格朗日插值法

观察式子:

\[G(k) = \sum_{i = 0}^n y_i \prod_{i \not = j} \dfrac{k - x_j}{x_i - x_j} \]

\(g = \prod_{i = 0}^n (k - x_i)\) ,则:

\[G(k) = g \sum_{i = 0}^n \prod_{i \not = j} \dfrac{y_i}{(k - x_i)(x_i - x_j)} \]

再令 \(t_i = \dfrac{y_i}{\prod_{j \not = i} x_i - x_j}\) ,则:

\[G(k) = g \sum_{i = 0}^n \dfrac{t_i}{k - x_i} \]

这样每次新加入一个点的时候只需要计算 \(g, t_i\) 即可。

应用

The Sum of the k-th Powers

给定 \(n, k\) ,求 \((\sum_{i = 1}^n i^k) \bmod 10^9 + 7\)

\(1 \leq n \leq 10^9, 0 \leq k \leq 10^6\)

有一个结论:\(\sum_{i = 1}^n i^k\) 是一个 \(k + 1\) 次多项式。

定义数列 \(\{a_n\}\)\(p\) 阶差分数列为 \(\Delta^p f(x) = \Delta(\Delta^{p - 1}f(x))\) 。若数列 \(\{a_n\}\)\(p\) 阶阶差数列是一个非 \(0\) 的常数列,那么我们称数列 \(\{a_n\}\)\(p\) 阶等差数列

定理:数列 \(\{a_n\}\) 是一个 \(p\) 阶等差数列的充要条件是其通项公式是一个关于 \(n\)\(p\) 次多项式

先证明其充分性,必要性的证法也是类似的。设数列的通项公式 \(f(x) = \sum_{i = 0}^n a_ix^i\) ,则其一次差分数列的通项公式为:

\[\begin{aligned} \Delta f(x) &= f(x + 1) - f(x) \\ &= \sum_{i = 0}^n a_i(x + 1)^i - \sum_{i = 0}^n a_ix^i \\ &= \sum_{i = 0}^n a_i[(x + 1)^i - x^i] \end{aligned} \]

我们只考虑 \(x_n\) 项得到可能得到它的只有这个式子:

\[a_n[(x + 1)^n - x^n] \]

我们把 \((x + 1)^n\) 用二项式定理展开,因为只考虑 \(n\) 次项,所以我们只保留 \(x^n\) ,发现其系数为 \(1\) ,刚好和后面的项消掉。所以将数列差分一次后就会消掉最高次项。类似的, \(p\) 次差分后就会消掉 \(p\) 次项,所以这个数列的通项公式是一个关于 \(n\)\(p\) 次多项式。

设数列 \(\{a_n\}\) 的通项公式为 \(a_n = \sum_{i = 1}^n i^k\) ,其差分数列的通项公式为 \(f(x) = x^k\) 是一个 \(k\) 次多项式,所以这个数列是一个关于 \(n\)\(k + 1\) 次多项式。

那么我们为了确定这个 \(k + 1\) 次多项式,我们需要 \(k + 2\) 个点来确定。令这些点的坐标为 \(1 \sim k + 2\) ,即可 \(O(n)\) 求解。因为 \(i^k\) 是完全积性函数,可以线性筛。

P5667 拉格朗日插值2

给定一个不超过 \(n\) 次的多项式的 \(n+1\) 个点值 \(f(0),f(1) \dots f(n)\),和一个正整数 \(m\),求 \(f(m),f(m+1) \dots f(m+n)\) 。答案对 \(998244353\) 取模。

\(n \leq 1.6 \times 10^5\)\(n < m \leq 10^8\)

由插值公式可得:

\[\begin{aligned} f(m + x) &= \sum_{i = 0}^n f(i) \prod_{j \not = i} \dfrac{m + x - j}{i - j} \\ &= \sum_{i = 0}^n f(i) \dfrac{\dfrac{(m + x)!}{(m + x - n - 1)!}}{(m + x - i) (-1)^{n - i} i! (n - i)!} \end{aligned} \]

令:

\[\begin{aligned} u_i &= \begin{cases} \dfrac{f(i)}{(-1)^{n - i} i! (n - i)!} & i \leq n \\ 0 & i > n \end{cases} \\ v_i &= \dfrac{1}{m - n + i} \end{aligned} \]

可得:

\[f(m + x) = (u \times v)[n + x] \prod_{i = m + x - n}^{m + x} i \]

NTT 即可。

inline void Lagrange(int *f, int n, int *res, int m) {
	static int u[N], v[N];
	
	for (int i = 0; i <= 2 * n; ++i) {
		u[i] = i <= n ? 1ll * f[i] * sgn(n - i) % Mod * invfac[i] % Mod * invfac[n - i] % Mod : 0;
		v[i] = mi(m - n + i, Mod - 2);
	}
	
	Poly::Mul(u, 2 * n + 1, v, 2 * n + 1, u);
	int prod = 1;
	
	for (int i = m - n; i <= m; ++i)
		prod = 1ll * prod * i % Mod;
	
	for (int i = 0; i <= n; ++i) {
		res[i] = 1ll * u[n + i] * prod % Mod;
		prod = 1ll * prod * mi(m + i - n, Mod - 2) % Mod * (m + i + 1) % Mod;
	}
}
posted @ 2024-07-30 14:38  我是浣辰啦  阅读(9)  评论(0编辑  收藏  举报