【算法讲14:拉格朗日插值】

  • 前言
  • 引入
  • ⌈\lceil⌈拉格朗日插值⌋\rfloor⌋
  • 代码
  • ⌈\lceil⌈拉格朗日插值⌋\rfloor⌋差分法运用
  • 代码

前言

  • 拉格朗日插值可以出的很难,对于一个 nnn 阶多项式,可以优化成 O(nlog⁡n)O(n\log n)O(nlogn)
    但是需要 FFTFFTFFT 等知识点,博主比较菜就只能搞搞入门的了 (哭)
  • 基础的高斯消元法可以 O(n3)O(n^3)O(n3) 求解 nnn 阶多项式,但是貌似不够用呀
    这时就出现了 O(n2)O(n^2)O(n2) 的拉格朗日插值!
    对于能求出 f(i),∀i∈[1,n]f(i),\forall i\in[1,n]f(i),∀i∈[1,n],我们用 差分法 还可以化简到 O(n)O(n)O(n)

引入

  • 【题目描述】【模板】拉格朗日插值 | 洛谷 P4781
    有 nnn 个不同点,给定他们的坐标 (xi,yi)(x_i,y_i)(xi​,yi​)
    由于他们的横坐标都不相同,因此他们可以唯一确定一个 n−1n-1n−1 阶的多项式 P(x)P(x)P(x)
    给定 kkk ,你的任务是求出 P(k)P(k)P(k) 取模 998244353998244353998244353
  • 【数据范围】
    1≤n≤2×1031\le n\le 2\times10^31≤n≤2×103
    1≤xi,yi,k<9982443531\le x_i,y_i,k<9982443531≤xi​,yi​,k<998244353

⌈\lceil⌈拉格朗日插值⌋\rfloor⌋

  • 我们知道多项式可以表示为 P(x)=∑aixiP(x)=\sum a_ix^iP(x)=∑ai​xi。
    很神奇的,我们想构造出一个函数来表示这个 P(x)P(x)P(x)
  • 我们设一个函数:
    li(x)=∏j=0,j≠inx−xjxi−xjl_i(x)=\prod_{j=0,j\ne i}^n\cfrac{x-x_j}{x_i-x_j}li​(x)=j=0,j​=i∏n​xi​−xj​x−xj​​
    这个函数有什么性质呢?有一下两个性质:
    (1)∀i∈[0,n],li(xi)=1\forall i\in[0,n],l_i(x_i)=1∀i∈[0,n],li​(xi​)=1
    (2)∀i,j∈[0,n],i≠j,li(xj)=0\forall i,j\in[0,n],i\ne j,l_i(x_j)=0∀i,j∈[0,n],i​=j,li​(xj​)=0
    接下来,我们就能直接构造出 P(x)P(x)P(x)了:
    P(x)=∑i=0nyili(x)P(x)=\sum_{i=0}^n y_il_i(x) P(x)=i=0∑n​yi​li​(x)
    为啥这个多项式保证是正确的呢?因为我们有:
    ∀i∈[0,n],P(xi)=yi\forall i\in[0,n],P(x_i)=y_i∀i∈[0,n],P(xi​)=yi​,保证成立。

代码

  • 时间复杂度:O(n2)O(n^2)O(n2)
const int MAX = 2e3+50;
const ll  MOD = 998244353;ll qpow(ll a,ll n){/* */ll res = 1LL;while(n){if(n&1)res=res*a%MOD;a=a*a%MOD;n>>=1;}return res;}
ll inv(ll a){/* */return qpow(a,MOD-2);}ll X[MAX],Y[MAX];int main()
{int n;ll k;cin >> n >> k;for(int i = 0;i < n;++i){cin >> X[i] >> Y[i];}ll res = 0;for(int i = 0;i < n;++i){ll num = Y[i];ll den = 1;for(int j = 0;j < n;++j){if(i != j){num = num * (k - X[j]) % MOD;den = den * (X[i] - X[j]) % MOD;}}num = (num + MOD) % MOD;den = (den + MOD) % MOD;res = (res + num % MOD * inv(den) % MOD) % MOD;}cout << res;return 0;
}

⌈\lceil⌈拉格朗日插值⌋\rfloor⌋差分法运用

  • 【题目描述】The Sum of the k-th Powers | CF 622F
    给定 n、kn、kn、k,求:
    ∑i=1nik\sum_{i=1}^ni^k i=1∑n​ik
  • 【数据范围】
    1≤n≤1091\le n\le 10^91≤n≤109
    1≤k≤1061\le k\le 10^61≤k≤106
  • 【思路】
    这下阶为 1e61e61e6了,O(k2)O(k^2)O(k2) 已经不适用了。
    我们如果算出前面一些 xix_ixi​ 和 yiy_iyi​,想快速算 li(n)l_i(n)li​(n),怎么办呢?
    如果我们令 xi=ix_i=ixi​=i,那么式子会变成下面的样子:
    li(n)=∏j=1,j≠ikn−ji−jl_i(n)=\prod_{j=1,j\ne i}^k\cfrac{n-j}{i-j} li​(n)=j=1,j​=i∏k​i−jn−j​
    (1)对于分子,我们只要预处理出一个前缀积和后缀积,即可快速算。
    令 pre(i)=∏j=1in−jpre(i)=\prod_{j=1}^i n-jpre(i)=∏j=1i​n−j,suf(i)=∏j=ikn−jsuf(i)=\prod_{j=i}^k n-jsuf(i)=∏j=ik​n−j
    那么分子就是 pre(i−1)×suf(i+1)pre(i-1)\times suf(i+1)pre(i−1)×suf(i+1)
    (2)对于分母,容易想到就是一个 断开的阶乘,就是 fac[i−1]×fac[k−i]fac[i-1]\times fac[k-i]fac[i−1]×fac[k−i]
    不过要注意一下,因为当 j>ij>ij>i 时,后面每一项都为负数。若 k−ik-ik−i是一个奇数,那么后面会多一个负号。
    P(n)=∑i=1kyi×pre(i−1)×suf(i+1)fac[i]×fac[k−i]×(−1)k−iP(n)=\sum_{i=1}^ky_i\times\cfrac{pre(i-1)\times suf(i+1)}{fac[i]\times fac[k-i]}\times(-1)^{k-i} P(n)=i=1∑k​yi​×fac[i]×fac[k−i]pre(i−1)×suf(i+1)​×(−1)k−i
    这下,时间复杂度变为线性的了!

代码

  • 342Ms/2000Ms342Ms/2000Ms342Ms/2000Ms
    时间复杂度:O(k)O(k)O(k)
/*_            __   __          _          _
| |           \ \ / /         | |        (_)
| |__  _   _   \ V /__ _ _ __ | |     ___ _
| '_ \| | | |   \ // _` | '_ \| |    / _ \ |
| |_) | |_| |   | | (_| | | | | |___|  __/ |
|_.__/ \__, |   \_/\__,_|_| |_\_____/\___|_|__/ ||___/
*/
const int MAX = 1e6+50;
const ll  MOD = 1e9+7;ll qpow(ll a,ll n){/* */ll res = 1LL;while(n){if(n&1)res=res*a%MOD;a=a*a%MOD;n>>=1;}return res;}
ll inv(ll a){/* */return qpow(a,MOD-2);}ll Y[MAX];
ll fac[MAX];
ll ivfac[MAX];
ll pre[MAX],suf[MAX];
void init(ll n,ll k){fac[0] = 1;pre[0] = 1;for(int i = 1;i <= k;++i){fac[i] = (fac[i-1] * i) % MOD;pre[i] = pre[i - 1] * (n - i) % MOD;}ivfac[k] = inv(fac[k]);suf[k+1] = 1;          /// 注意一下,不存在的话设为 1suf[k] = n - k;for(int i = k - 1;i >= 0;--i){ivfac[i] = ivfac[i + 1] * (i + 1) % MOD;suf[i] = suf[i + 1] * (n - i) % MOD;}
}
int main()
{ll n,k;cin >> n >> k;k += 2;         /// 因为是 k+2 阶的多项式init(n,k);ll sum = 0;for(int i = 1;i <= k;++i){sum  = (sum + qpow(i,k - 2)) % MOD;Y[i] = sum;if(n == i){cout << sum;return 0;}}ll res = 0;for(int i = 1;i <= k;++i){ll num = Y[i] * pre[i - 1] % MOD * suf[i + 1] % MOD;ll den = ivfac[i - 1] * ivfac[k - i] % MOD;if((k - i) % 2 == 1)den = -den;res = (res + num * den) % MOD;}res = (res + MOD) % MOD;cout << res;return 0;
}

【算法讲14:拉格朗日插值】拉格朗日插值入门 与 拉格朗日插值差分法相关推荐

  1. matlab全域基函数,多项式函数插值:全域多项式插值(一)单项式基插值、拉格朗日插值、牛顿插值 [MATLAB]...

    全域多项式插值指的是在整个插值区域内形成一个多项式函数作为插值函数.关于多项式插值的基本知识,见"计算基本理论". 在单项式基插值和牛顿插值形成的表达式中,求该表达式在某一点处的值 ...

  2. 拉格朗日插值、分段线性插值、三次样条插值

    本篇主要介绍在三种插值方法:拉格朗日插值.分段线性插值.三次样条插值,以及这三种方法在matlab中如何实现. 1.拉格朗日插值: 1.1基本原理:先构造一组基函数:               是次 ...

  3. 数学建模准备 插值(拉格朗日多项式插值,牛顿多项式插值,分段线性插值,分段三次样条插值,分段三次Hermite插值)

    文章目录 摘要(必看) 0 基础概念 什么是插值 插值用途 什么是拟合 插值和拟合的相同点 插值和拟合的不同点 1 常用的基本插值方法 1.1 多项式插值法 1.1.1 拉格朗日多项式插值法 多项式插 ...

  4. 插值与拟合 (一) : 拉格朗日多项式插值 、Newton插值 、分段线性插值、Hermite插值 、样条插值、 B 样条函数插值、二维插值

    插值:求过已知有限个数据点的近似函数. 拟合:已知有限个数据点,求近似函数,不要求过已知数据点,只要求在某种意义下它在这些点上的总偏差最小. 插值和拟合都是要根据一组数据构造一个函数作为近似,由于近似 ...

  5. 从放弃到再入门之拉格朗日对偶问题推导(转)

    从放弃到再入门之拉格朗日对偶问题推导(转) 2018年04月17日 16:15:33 EFLYP  普通同学的解法 无约束条件:求导就可以了 等式约束:代入消元,再求导 不等式约束:分情况讨论(在边界 ...

  6. 【数学与算法】【分段三次Hermite插值】和【分段三次样条插值】

    光滑曲线在数学上的定义是什么?? 原文链接:光滑曲线在数学上的定义是什么? 回答1: 定义:切线随切点的移动而连续转动. 若函数f(x)f(x)f(x)在区间(a,b)(a,b)(a,b)内具有一阶连 ...

  7. python 克里金空间插值_Python克里金(Kriging)插值计算及可视化绘制

    前面两篇推文我们分别介绍了使用Python和R进行IDW(反距离加权法) 插值的计算及结果的可视化过程,详细内容可见如下: 本期推文,我们将介绍如何使用Python进行克里金(Kriging)插值计算 ...

  8. 杭电ACM-LCY算法进阶培训班-专题训练(计算几何入门)

    杭电ACM-LCY算法进阶培训班-专题训练(计算几何入门) 传送门 杭电ACM-LCY算法进阶培训班-专题训练(计算几何入门) Shape of HDU Problem Description Inp ...

  9. 拉格朗日乘数法及python实现拉格朗日乘数法

    拉格朗日乘数法(Lagrange Multiplier Method)基本思想 作为一种优化算法,拉格朗日乘子法主要用于解决约束优化问题,它的基本思想就是通过引入拉格朗日乘子来将含有n个变量和k个约束 ...

最新文章

  1. 第十二届西南石油大学程序设计新生赛官方题解
  2. c#_Math.Sign()
  3. 七、【SAP-PM模块】信息系统 报表分析
  4. OCR 深度学习 综述
  5. micropython会商用吗_NSF商用食品设备认证解析
  6. Boost多线程-替换MFC线程
  7. python基本语法:列表(列表和元组的区别)
  8. python机器学习2021年6月19日09:35:06
  9. 计算机学科研究方向统计
  10. 《剑指 Offer I》刷题笔记 1 ~10 题
  11. python md5加密解密_Python使用MD5加密算法对字符串进行加密操作示例
  12. 常用类字符串详解大全String
  13. Xilinx官方文档检索说明
  14. Git报错remote: error: hook declined to update refs/heads/feature/XXX
  15. 女生应该读的30本书
  16. Mockito when函数实现方式
  17. 不等式解集怎么取_不等式的解集怎么求
  18. 求最大连续区间和的几种方法
  19. 开始搞点其他的事-成立北京租房群(霍营、回龙观、西二旗、望京)
  20. 解决Win7添加网络打印机报错0x000003e3

热门文章

  1. Android 发布开源项目到jcenter
  2. android怎么自动收起通知栏,Android中如何收起状态栏
  3. 显微镜下的webpack4入门
  4. Part-Ⅰ4. 开关实现(一)
  5. 微信小程序怎么把获取的值传到引用组件内_微信小程序如何将接口获取的数据传递给自定义组件...
  6. 中国房地产数字化厂商全景报告
  7. 多个数组间元素排列组合问题求解(Java实现)
  8. 关于Hibernate中的临时态, 持久态, 游离态
  9. 2020年市政方向-通用基础(施工员)模拟试题及市政方向-通用基础(施工员)模拟考试题
  10. phpinfo.php的含义,phpinfo什么意思