拉格朗日插值法

简陋的拉格朗日插值法学习过程

题目

已知 \(n\) 个点,确定了一个 \(n-1\) 次多项式 \(f\),求 \(f(x)\)

拉格朗日插值法

\[f(x)=\sum_{i=1}^ny_i\prod_{j \ne i}\frac{x-x_j}{x_i-x_j} \]

即可 \(O(n^2)\) 计算

模板

直接套用公式即可

\(\text{Code}\)

#include <cstdio>
#define LL long long
using namespace std;

const int N = 2e3 + 5;
const LL P = 998244353;
int n, k, x[N], y[N];

inline LL fpow(LL x, LL y)
{
	LL res = 1;
	for(; y; y >>= 1, x = x * x % P) if (y & 1) res = res * x % P;
	return res;
}

signed main()
{
	scanf("%d%d", &n, &k);
	for(int i = 1; i <= n; i++) scanf("%d%d", &x[i], &y[i]);
	LL ans = 0;
	for(int i = 1; i <= n; i++)
	{
		LL s1 = y[i], s2 = 1;
		for(int j = 1; j <= n; j++) 
		if (i != j) s1 = s1 * (k - x[j] + P) % P, s2 = s2 * (x[i] - x[j] + P) % P;
		ans = (ans + s1 * fpow(s2, P - 2) % P) % P;
	}
	printf("%lld\n", ans);
}

自然数幂和

一个结论,和式是一个关于 \(n\)\(k+1\) 次多项式
把前 \(k+2\) 个点带进公式求 \(f(n)\) 即可
因为分母是阶乘形式的,分子分母都可以预处理
可以做到 \(O(n \log n)\)

\(\text{Code}\)

#include <cstdio>
#define re register
using namespace std;
typedef long long LL;

const int P = 1e9 + 7, N = 1e6 + 10;
int n, k;
LL pre[N], suf[N], fac[N];

inline int fpow(int x, int y)
{
	x = (x + P) % P;
	int res = 1;
	for(; y; y >>= 1, x = 1LL * x * x % P) if (y & 1) res = 1LL * res * x % P;
	return res;
}

int main()
{
	scanf("%d%d", &n, &k);
	pre[0] = 1, suf[k + 3] = 1, fac[0] = 1;
	for(re int i = 1; i <= k + 2; i++) pre[i] = pre[i - 1] * (n - i + P) % P;
	for(re int i = k + 2; i; i--) suf[i] = suf[i + 1] * (n - i + P) % P;
	for(re int i = 1; i <= k + 2; i++) fac[i] = fac[i - 1] * i % P;
	int ans = 0, x, y = 0;
	for(re int i = 1; i <= k + 2; i++)
		x = fpow(fac[i - 1] * ((k - i) & 1 ? -1 : 1) * fac[k + 2 - i] % P, P - 2),
		y = (y + fpow(i, k)) % P, ans = (ans + pre[i - 1] * suf[i + 1] % P * x % P * y % P) % P;
	printf("%d\n", ans);
}
posted @ 2021-10-29 13:25  leiyuanze  阅读(223)  评论(1编辑  收藏  举报