拉格朗日插值算法

首先介绍下作用

在平面上给定 n 个点,求一条多项式图像穿过所有的点

(每个点横坐标不同)

由浅入深,首先想一个悬浮点 1 ,它在除 1 以外给定的点的横坐标上函数值都是 0 。已知它的横坐标 \(x_1\) , 怎么用函数图像表示

我们一拍脑袋发现,可以这么表示

\[f1(x) = \prod_{i = 2}^n {x - x_i} \]

这一坨是不是在给定点的横坐标中,只当横坐标是点 \(x_1\) 的时候不为 0

然而实际上这个东西的纵坐标不太可控,所以我们把这玩意再除一下,让横坐标是 \(x_1\) 时纵坐标为 1, 方便后续操作

\[f1(x) = \prod_{i = 2}^n \frac{x - x_i}{x_1 - x_i} \]

下一个目标其实也简单,就是把这个点的纵坐标改变,比如我们现在已知这个点 1 的纵坐标为 \(y_1\) ,式子就变成

\[f1(x) = y_1 \times \prod_{i = 2}^n \frac{x - x_i}{x_1 - x_i} \]

更具有普遍性,一个点 i , 横坐标 \(x_i\) , 纵坐标 \(y_i\),以下这个函数的图像一定经过它

\[f(x) = y_i \times \prod_{j \ne i}^{n} \frac{x - x_j}{x_i - x_j} \]

那么我们可以列举一大堆函数,这些函数都是只在单个点的横坐标上取值为纵坐标,其他给定点上函数值都是 0

比如 刚才的 \(f1(x)\) ,给定点中只在第一个点上取得值是 \(y_i\) ,其他都是 0

那我们是不是就可以用一个求和的形式了捏 ? 这样他就会在不同给定点的坐标自动给出值

\[f(k) = \sum_{i = 1}^{n} y_i \times \prod_{j \ne i}^{n} \frac{k - x_j}{x_i - x_j} \]

这就是经过 n 个点的函数。说到这里,其实板子已经能做了

洛谷P4781 拉格朗日插值

放下代码罢,马蜂诡奇,勿喷拜谢

#include <bits/stdc++.h>

#define mod 998244353
#define ri register int
#define N 2007
#define int long long

int x[N] , y[N];
namespace P4781 {
	int n , k , sum = 0;
	inline int Pow(int a , int b) {
		int ans = 1;
		while(b) {
			if(b & 1) {
				ans = ans * a % mod;
			}
			a = a * a % mod;
			b >>= 1;
		}
		return ans % mod;
	}
	
	void solve() {
		sum = 0;
		scanf("%lld%lld",&n,&k);
		for(ri i = 1; i <= n; ++i) {
			scanf("%lld%lld", &x[i] , &y[i]);
		}
		for(ri i = 1; i <= n; ++i) {
			int res = 1;
			for(ri j = 1; j <= n; ++j) {
				if(i == j) {
					continue;
				}
				res = (res * (k - x[j] + mod) % mod * Pow(x[i] - x[j] , mod - 2) % mod + mod) % mod;
			}
			res = res * y[i] % mod;
			sum = (sum + res) % mod;
		}
		
		printf("%lld",sum % mod);
	}
}

signed main() {
	P4781 :: solve();
	return 0;
}
posted @ 2025-03-16 22:55  「癔症」  阅读(25)  评论(0)    收藏  举报