拉格朗日插值法
拉格朗日插值法
对任意一个 x x x求 f ( x ) f(x) f(x)
给定一个
n
n
n次多项式(共有
n
+
1
n+1
n+1项)
f
(
x
)
=
a
0
+
a
1
x
+
a
2
x
2
+
⋯
+
a
n
x
n
f(x)=a_{0}+a_{1}x+a_{2}x^2+\cdots+a_{n}x^n
f(x)=a0+a1x+a2x2+⋯+anxn
对于函数,若已知其任意 n + 1 n+1 n+1个x的取值以及其所对应的 f ( x ) f(x) f(x)(即为 y y y),可以利用拉格朗日插值来求其他任意 X X X的 f ( X ) f(X) f(X)
f ( X ) = L ( X ) = ∑ i = 0 n y i ∗ l i ( x ) = ∑ i = 0 n y i ∗ ∏ j ≠ j j < = n X − x j x i − x j f(X)=L(X)=\sum_{i=0}^{n}y_{i}*l{i}(x)=\sum_{i=0}^{n}y_{i}*\prod_{j\neq j}^{j<=n}\frac{X-x_{j}}{x_{i}-x_{j}} f(X)=L(X)=i=0∑nyi∗li(x)=i=0∑nyi∗j̸=j∏j<=nxi−xjX−xj
以
f
(
1
)
=
1
,
f
(
2
)
=
4
,
f
(
3
)
=
9
f(1)=1,f(2)=4,f(3)=9
f(1)=1,f(2)=4,f(3)=9为例
l
1
(
x
)
=
x
−
2
1
−
2
∗
x
−
3
1
−
3
l_{1}(x)=\frac{x-2}{1-2}*\frac{x-3}{1-3}
l1(x)=1−2x−2∗1−3x−3
l
2
(
x
)
=
x
−
1
2
−
1
∗
x
−
3
2
−
3
l_{2}(x)=\frac{x-1}{2-1}*\frac{x-3}{2-3}
l2(x)=2−1x−1∗2−3x−3
l
3
(
x
)
=
x
−
1
3
−
1
∗
x
−
2
3
−
2
l_{3}(x)=\frac{x-1}{3-1}*\frac{x-2}{3-2}
l3(x)=3−1x−1∗3−2x−2
f
(
X
)
=
f
(
1
)
∗
l
1
(
X
)
+
f
(
2
)
∗
l
2
(
x
)
+
f
(
3
)
∗
l
3
(
x
)
f(X)=f(1)*l_{1}(X)+f(2)*l_{2}(x)+f(3)*l_{3}(x)
f(X)=f(1)∗l1(X)+f(2)∗l2(x)+f(3)∗l3(x)
=
1
∗
x
−
2
1
−
2
∗
x
−
3
1
−
3
+
4
∗
x
−
1
2
−
1
∗
x
−
3
2
−
3
+
9
∗
x
−
1
3
−
1
∗
x
−
2
3
−
2
=1*\frac{x-2}{1-2}*\frac{x-3}{1-3}+4*\frac{x-1}{2-1}*\frac{x-3}{2-3}+9*\frac{x-1}{3-1}*\frac{x-2}{3-2}
=1∗1−2x−2∗1−3x−3+4∗2−1x−1∗2−3x−3+9∗3−1x−1∗3−2x−2
=
x
2
=x^2
=x2
带入公式对于任意一个x是
O
(
n
)
O(n)
O(n)的,多次询问即为
O
(
n
2
)
O(n^2)
O(n2)
已知 f ( x ) f(x) f(x)为连续的求 f ( n ) f(n) f(n)
l 0 ( x ) = ( x − 1 ) ( x − 2 ) ⋯ ( x − n ) ( 0 − 1 ) ( 0 − 2 ) ⋯ ( 0 − n ) l_{0}(x)=\frac{(x-1)(x-2)\cdots(x-n)}{(0-1)(0-2)\cdots(0-n)} l0(x)=(0−1)(0−2)⋯(0−n)(x−1)(x−2)⋯(x−n) l 1 ( x ) = ( x − 0 ) ( x − 2 ) ⋯ ( x − n ) ( 1 − 0 ) ( 1 − 2 ) ⋯ ( 0 − n ) l_{1}(x)=\frac{(x-0)(x-2)\cdots(x-n)}{(1-0)(1-2)\cdots(0-n)} l1(x)=(1−0)(1−2)⋯(0−n)(x−0)(x−2)⋯(x−n) ⋯ ⋯ \cdots\cdots ⋯⋯ l n ( x ) = ( x − 0 ) ( x − 1 ) ⋯ ( x − ( n − 1 ) ) ( n − 0 ) ( n − 1 ) ⋯ ( n − ( n − 1 ) ) l_{n}(x)=\frac{(x-0)(x-1)\cdots(x-(n-1))}{(n-0)(n-1)\cdots(n-(n-1))} ln(x)=(n−0)(n−1)⋯(n−(n−1))(x−0)(x−1)⋯(x−(n−1))
分子:
令
M
=
(
x
−
0
)
(
x
−
1
)
(
x
−
2
)
⋯
(
x
−
n
)
M=(x-0)(x-1)(x-2)\cdots(x-n)
M=(x−0)(x−1)(x−2)⋯(x−n)
l
i
(
x
)
l_{i}(x)
li(x)的分子为
M
/
(
x
−
i
)
M/(x-i)
M/(x−i)
分母
l
0
(
x
)
−
>
(
−
1
)
n
∗
0
!
∗
n
!
l_{0}(x)->(-1)^n*0!*n!
l0(x)−>(−1)n∗0!∗n!
l
1
(
x
)
−
>
(
−
1
)
n
−
1
∗
1
!
∗
(
n
−
1
)
!
l_{1}(x)->(-1)^{n-1}*1!*(n-1)!
l1(x)−>(−1)n−1∗1!∗(n−1)!
l
2
(
x
)
−
>
(
−
1
)
n
−
2
∗
2
!
∗
(
n
−
2
)
!
l_{2}(x)->(-1)^{n-2}*2!*(n-2)!
l2(x)−>(−1)n−2∗2!∗(n−2)!
分母为:
(
−
1
)
n
−
i
∗
i
!
∗
(
n
−
i
)
!
(-1)^{n-i}*i!*(n-i)!
(−1)n−i∗i!∗(n−i)!
n!的逆元
先用费马小定理求出
n
!
n!
n!的逆元
1
(
n
−
1
)
!
=
1
n
!
∗
n
m
o
d
  
m
o
d
\frac{1}{(n-1)!}=\frac{1}{n!}*n\mod mod
(n−1)!1=n!1∗nmodmod
Polynomial
题意
已知
f
(
x
)
=
a
0
+
a
1
x
+
a
2
x
2
+
⋯
+
a
n
n
f(x)=a_{0}+a_{1}x+a_{2}x^2+\cdots+a_{n}^n
f(x)=a0+a1x+a2x2+⋯+ann
你知道
f
(
0
)
,
f
(
1
)
,
f
(
2
)
,
⋯
 
,
f
(
n
)
f(0),f(1),f(2),\cdots,f(n)
f(0),f(1),f(2),⋯,f(n)
求
∑
i
=
L
R
f
(
i
)
\sum_{i=L}^{R}f(i)
∑i=LRf(i)
分析
已知
f
(
0
)
=
a
0
+
a
1
0
+
a
2
0
2
+
⋯
+
a
n
0
n
f(0)=a_{0}+a_{1}0+a_{2}0^2+\cdots+a_{n}0^n
f(0)=a0+a10+a202+⋯+an0n
f
(
1
)
=
a
0
+
a
1
1
+
a
2
1
2
+
⋯
+
a
n
1
n
f(1)=a_{0}+a_{1}1+a_{2}1^2+\cdots+a_{n}1^n
f(1)=a0+a11+a212+⋯+an1n
f
(
2
)
=
a
0
+
a
1
2
+
a
2
2
2
+
⋯
+
a
n
2
n
f(2)=a_{0}+a_{1}2+a_{2}2^2+\cdots+a_{n}2^n
f(2)=a0+a12+a222+⋯+an2n
⋯
⋯
\cdots\cdots
⋯⋯
f
(
n
)
=
a
0
+
a
1
n
+
a
2
n
2
+
⋯
+
a
n
n
n
f(n)=a_{0}+a_{1}n+a_{2}n^2+\cdots+a_{n}n^n
f(n)=a0+a1n+a2n2+⋯+annn
显然,对 1 n + 2 n + 3 n + ⋯ + x n = b 0 x n + 1 1^n+2^n+3^n+\cdots+x^n=b_{0}x^{n+1} 1n+2n+3n+⋯+xn=b0xn+1
S ( n ) = ∑ i = 1 n f ( i ) = b 0 + b 1 n + b 2 n 2 + ⋯ + b n n n + b n + 1 n n + 1 S(n)=\sum_{i=1}^{n} f(i)=b_{0}+b_{1}n+b_{2}n^2+\cdots+b_{n}n^n+b_{n+1}n^{n+1} S(n)=i=1∑nf(i)=b0+b1n+b2n2+⋯+bnnn+bn+1nn+1
先用拉格朗日插值推出
a
n
+
1
a_{n+1}
an+1,再推出
S
(
0
)
,
S
(
1
)
,
⋯
 
,
S
(
n
)
,
S
(
n
+
1
)
S(0),S(1),\cdots,S(n),S(n+1)
S(0),S(1),⋯,S(n),S(n+1)
再用拉格朗日插值推出
S
(
R
)
−
S
(
L
−
1
)
S(R)-S(L-1)
S(R)−S(L−1)
代码
预处理
fac[0] = 1; //阶乘
for (int i = 1; i <= maxn; i++)
fac[i] = fac[i] * i % mod;
inv[1] = 1; //逆元
for (int i = 2; i <= maxn; i++)
inv[i] = (mod - mod / i) * (LL)1 * inv[mod % i] % mod;
fac_inv[maxn] = quickpow(fac_inv[maxn], mod - 2); //n!的逆元
for (int i = maxn - 1; i >= 1; i--)
fac_inv[i] = fac_inv[i + 1] * (i + 1) % mod;
拉格朗日插值 f ( n + 1 ) f(n+1) f(n+1)
void Get_f_next() { //计算a[n+1]
f[n + 1] = 0;
LL M = 1; //处理分子
for (int i = 0; i <= n; i++)
M = M * (n + 1 - i) % mod;
LL ans = 0; //拉格朗日插值
for (int i = 0; i <= n; i++) {
ans = M * inv[n + 1 - i] % mod //分子
* fac_inv[n-i] % mod * fac_inv[i] % mod; //分母
if ((n - i) & 1)f[n + 1] = (f[n + 1] - ans * f[i] % mod + mod) % mod; //yi*li
else f[n + 1] = (f[n + 1] + ans * f[i] % mod + mod) % mod;
}
}
拉格朗日插值 S ( r ) S(r) S(r)
LL Get_S(LL r) {
if (r <= n + 1)
return sum[r];
LL M = 1;
for (int i = 0; i <= n + 1; i++) //处理分子
M = M * LL(r - i) % mod; //分母
LL ans = 0, res = 0;
for (int i = 0; i <= n + 1; i++) {
ans = M * inv[r - i] % mod //分子
* fac_inv[n + 1 - i] % mod * fac_inv[i] % mod; //分母
if ((n + 1 - i) & 1) res = (res - ans * sum[i] % mod + mod) % mod; //yi*li
else res = (res + ans * sum[i] % mod + mod) % mod;
}
return res;
}
完整代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
#pragma warning (disable:4996)
typedef long long LL;
const int maxn = 1005;
const LL mod = 9999991;
LL fac[maxn + 5], inv[mod + 100], fac_inv[maxn + 5];
LL quickpow(LL m, LL p) {
LL res = 1;
while (p) {
if (p & 1)
res = res * m % mod;
m = m * m % mod;
p >>= 1;
}
return res;
}
void init() {
fac[0] = 1;
for (int i = 1; i <= maxn; i++)
fac[i] = fac[i - 1] * LL(i) % mod;
fac_inv[maxn] = quickpow(fac[maxn], mod - 2);
for (int i = maxn - 1; i >= 0; i--)
fac_inv[i] = fac_inv[i + 1] * (LL(i) + 1) % mod;
inv[0] = inv[1] = 1;
for (int i = 2; i < mod+5; i++)
inv[i] = (mod - mod / i) * (LL)1 * inv[mod % i] % mod;
}
LL t, n, m;
LL f[maxn], sum[maxn];
void Get_f_next() { //计算a[n+1]
f[n + 1] = 0;
LL M = 1; //处理分子
for (int i = 0; i <= n; i++)
M = M * (n + 1 - i) % mod;
LL ans = 0; //拉格朗日插值
for (int i = 0; i <= n; i++) {
ans = M * inv[n + 1 - i] % mod //分子
* fac_inv[n-i] % mod * fac_inv[i] % mod; //分母
if ((n - i) & 1)f[n + 1] = (f[n + 1] - ans * f[i] % mod + mod) % mod; //yi*li
else f[n + 1] = (f[n + 1] + ans * f[i] % mod + mod) % mod;
}
}
LL Get_S(LL r) {
if (r <= n + 1)
return sum[r];
LL M = 1;
for (int i = 0; i <= n + 1; i++) //处理分子
M = M * LL(r - i) % mod; //分母
LL ans = 0, res = 0;
for (int i = 0; i <= n + 1; i++) {
ans = M * inv[r - i] % mod //分子
* fac_inv[n + 1 - i] % mod * fac_inv[i] % mod; //分母
if ((n + 1 - i) & 1) res = (res - ans * sum[i] % mod + mod) % mod; //yi*li
else res = (res + ans * sum[i] % mod + mod) % mod;
}
return res;
}
int main() {
init();
scanf("%lld", &t);
while (t--) {
scanf("%lld%lld", &n, &m);
for (int i = 0; i <= n; i++) {
cin >> f[i]; f[i] %= mod;
}
Get_f_next();
sum[0] = f[0];
for (int i = 1; i <= n + 1; i++)
sum[i] = (sum[i - 1] + f[i]) % mod;
LL l, r;
while (m--) {
scanf("%lld%lld", &l, &r);
printf("%lld\n", (Get_S(r) - Get_S(l - 1) + mod) % mod);
}
}
}