【数学】拉格朗日插值法
作者:互联网
定义
对某个多项式函数,已知有
细节
拉格朗日插值法的 \(k\) 的取值很容易让人迷惑,本文中所有的公式、代码都用 \(k\) 表示多项式的最高次数,也就是不超过 \(k\) 次的多项式。
-
插值一个 \(k\) 次多项式函数需要 \(k+1\) 个点。
-
\(k\) 次多项式的部分和,是一个 \(k+1\) 次多项式,需要 \(k+2\) 个点。
代码
时间复杂度: \(O(k^2)\) 预处理拉格朗日多项式的分母,然后用前缀积和后缀积 \(O(k)\) 求解出分子。
typedef long long ll;
const int MOD = 1e9 + 7;
const int MAXN = 1000 + 5;
int y[MAXN], d[MAXN], pu[MAXN], su[MAXN];
int pow_mod(ll x, int n) {
ll res = 1LL;
while(n) {
if(n & 1) {
res *= x;
if(res >= MOD)
res %= MOD;
}
x *= x;
if(x >= MOD)
x %= MOD;
n >>= 1;
}
return (int)res;
}
void init_lagerange(int k) {
for(int i = 1; i <= k + 1; ++i) {
ll res = 1LL;
for(int j = 1; j <= k + 1; ++j) {
if(i == j)
continue;
int tmp = i - j;
if(tmp < 0)
tmp += MOD;
res *= tmp;
if(res >= MOD)
res %= MOD;
}
d[i] = pow_mod(res, MOD - 2);
}
}
int lagerange(int *y, int k, int xx) {
if(xx <= k + 1)
return y[xx];
for(int i = 1; i <= k + 1; ++i) {
pu[i] = xx - i;
if(pu[i] < 0)
pu[i] += MOD;
}
su[k + 2] = 1LL;
for(int i = k + 1; i >= 1; --i) {
ll tmp = 1LL * su[i + 1] * pu[i];
if(tmp >= MOD)
tmp %= MOD;
su[i] = (int)tmp;
}
pu[0] = 1LL;
for(int i = 1; i <= k + 1; ++i) {
ll tmp = 1LL * pu[i - 1] * pu[i];
if(tmp >= MOD)
tmp %= MOD;
pu[i] = (int)tmp;
}
int yy = 0;
for(int i = 1; i <= k + 1; ++i) {
ll tmp = 1LL * pu[i - 1] * su[i + 1];
if(tmp >= MOD)
tmp %= MOD;
tmp *= d[i];
if(tmp >= MOD)
tmp %= MOD;
tmp *= y[i];
if(tmp >= MOD)
tmp %= MOD;
yy += (int)tmp;
if(yy >= MOD)
yy -= MOD;
}
return yy;
}
拓展
重心拉格朗日插值法
每次新增一个点,得到一个新的函数,O(1)。
特殊点拉格朗日插值法
例如要求 \(\sum_{i=1}^ni^{k}\) 的值,众所周知这是一个 \(k+1\) 次多项式,需要 \(k+2\) 个点。
这个值有很多种求法,有 \(O(n\log k)\) 的朴素解法(枚举+快速幂),有 \(O(k^2)\) 的系数递推法,使用上述的适用范围广泛的拉格朗日插值法,也可以做到 \(O(k^2)\) 。
但这里可以选取一些特殊的点来加速拉格朗日插值法的分母的求解。通过选取一个等差数列,那么这个分母会变得非常有规律。简单起见可以取自然数或正整数。
也就是说,假如有办法自行选取点,则拉格朗日插值法优化为特殊点拉格朗日插值法,时间复杂度为 \(O(k)\) 。(忽略求解特殊点时的复杂度)
题外话: \(\sum_{i=1}^ni^{k}\) 这个的求解确实可以是 \(O(k)\) 的,求解特殊点的复杂度朴素解法(枚举+快速幂)是 \(O(k\log k)\) ,但是有一种奇怪的解法:线性筛。因为这是一个完全积性函数,即 \((pq)^k=p^kq^k\) ,快速幂求出所有质数位置的值,然后合数拆出一个最小质因子即可,因为质数大概有 \(O(k/{\ln k})\) 个,所以总体复杂度依然是 \(O(k)\) 。
标签:tmp,拉格朗,插值法,res,int,数学,MOD 来源: https://www.cnblogs.com/purinliang/p/13670493.html