码迷,mamicode.com
首页 > 其他好文 > 详细

拉格朗日插值法

时间:2017-10-02 15:49:35      阅读:248      评论:0      收藏:0      [点我收藏+]

标签:为我   eof   rod   set   表示   复杂   memset   没有   多少   

  给定 $n$ 个点 $(x_1, y_1), (x_2, y_2), ..., (x_n, y_n)$ , 其中 $x_1, x_2, ..., x_n$ 互不相等, 构造一个最高次不超过 $n-1$ 的多项式 $F(x)$ 过这 $n$ 个点.

  首先, 这个多项式有且仅有一个, 我们可以通过范德蒙矩阵有逆来说明, 接下来考虑构造.

  构造 $C_1(x), C_2(x), ..., C_n(x)$ , 其中 $C_i(x) = \left\{ \begin{aligned} 1, & x = x_i \\ 0, & x \ne x_i \end{aligned} \right.$ , 那么 $F(x) = \sum_{i = 1} ^ n C_i(x) y_i$ .

  先连乘上 $(n-1)$ 项 $(x - x_j)$ 使得 $\forall k \ne i, C_i(x_k) = 0$ , 再来保证第 $i$ 项满足 $C_i(x_i) = 1$, 构造得 $\begin{aligned} C_i(x) = \frac{\prod_{j \ne i} (x - x_j)}{\prod_{j \ne i} (x_i - x_j)} \end{aligned}$ .

  综上, 满足插值条件且最高次不超过 $n-1$ 次的多项式有且仅有 $\begin{aligned} F(x) = \sum_{i = 1} ^ n y_i \frac{ \prod_{k \ne i} (x - x_k)}{\prod_{k \ne i} (x_i - x_k)} \end{aligned}$ .  

 

  如果已经知道一个 $n$ 次多项式 $F(x)$ 的 $n+1$ 个点, 要反着求 $F(x)$ , 那么可以直接把 $n+1$ 个点代入拉格朗日插值法, 因为我们可以得到唯一的满足插值条件且最高次不超过 $n$ 的多项式, 而我们知道存在 $F(x)$ 满足这两个条件, 所以得到的就是 $F(x)$ .

  如果已经知道一个 $n$ 次多项式 $F(x)$ 的 $n+2$ 个点, 要反着求 $F(x)$ , 那么可以直接把 $n+2$ 个点代入拉格朗日插值法, 因为我们可以得到唯一的满足插值条件且最高次不超过 $n+1$ 的多项式, 而我们知道存在 $F(x)$ 满足这两个条件, 所以得到的就是 $F(x)$ .

  总之, 如果我们知道 $n$ 次多项式 $F(x)$ 的不少于 $n+1$ 个点, 那么可以直接将这些点代入拉格朗日插值法中, 反着求出 $F(x)$ . 也就不需要精细到恰好要代入多少个点, 这样会好实现很多.

  假如我把一个 $n$ 次多项式 $F(x)$ 的 $n$ 个点代入拉格朗日插值法中, 得到的又是什么? 根据相关理论, 得到的就是满足插值条件, 且最高次不超过 $n-1$ 次的多项式, 这个多项式与 $F(x)$ 没有半毛钱关系.

 

  给定 $n$ 个点, 求 $f(X)$ .

  时间复杂度为 $O(n ^ 2)$ .

 1 int Solve(int X) {
 2     int fx = 0;
 3     for (int i = 1; i <= n; i++) {
 4         int Up = 1, Dw = 1;
 5         for (int j = 1; j <= n; j++) if (i != j) {
 6             Up = 1LL * Up * (X - x[j]) % MOD;
 7             Dw = 1LL * Dw * (x[i] - x[j]) % MOD;
 8         }
 9         fx = (fx + 1LL * y[i] * Up % MOD * Inv(Dw)) % MOD;
10     }
11     return fx;
12 }

 

  给定 $n$ 个点, 求多项式 $f(x)$ 的系数表示.

  时间复杂度为 $O(n ^ 2)$ .

 1 void Solve(void) {
 2     memset(ans, 0, sizeof ans);
 3     
 4     memset(a, 0, sizeof a), a[0] = 1;
 5     for (int i = 1; i <= n; i++) {
 6         for (int j = n; j >= 0; j--) {
 7             a[j+1] = (a[j+1] + a[j]) % MOD;
 8             a[j] = -1LL * x[i] * a[j] % MOD;
 9         }
10     }
11     
12     for (int i = 1; i <= n; i++) {
13         memcpy(t, a, sizeof t), memset(b, 0, sizeof b);
14         for (int j = n; j >= 0; j--) {
15             b[j] = t[j+1];
16             t[j] = (t[j] + 1LL * b[j] * x[i]) % MOD;
17             t[j+1] = 0;
18         }
19         
20         int Mul = 1;
21         for (int j = 1; j <= n; j++) if (i != j)
22             Mul = 1LL * Mul * (x[i] - x[j]) % MOD;
23         Mul = 1LL * Inv(Mul) * y[i] % MOD;
24         
25         for (int j = 0; j <= n; j++) b[j] = 1LL * b[j] * Mul % MOD;
26         for (int j = 0; j <= n; j++) ans[j] = (ans[j] + b[j]) % MOD;
27     }
28 }

 

拉格朗日插值法

标签:为我   eof   rod   set   表示   复杂   memset   没有   多少   

原文地址:http://www.cnblogs.com/Sdchr/p/7619769.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!