【学习笔记】拉格朗日插值
【学习笔记】拉格朗日插值
介绍
拉格朗日插值是用来求高次多项式的一种方法。我们知道假设已经给定了 个点,那么一定会有一个唯一确定的 次的多项式,拉格朗日插值就是用来求这样的多项式的。
实现
给出拉格朗日插值的式子,假设已经给定了 个点,分别为 那么
可以发现,对于第 项,如果 为 则值为 ,否则为 。因此把 带入可得 。暴力求解时间复杂度
The Sum of the k-th Powers
思路
首先证明一个结论:对于一个通项公式为 次的数列 ,每进行一次差分,生成新序列的通项公式的最高次数就会减 。
首先设序列的通项公式为 ,其中 为系数,则他的一阶差分的通项公式为
将其用二项式定理拆开,然后发现 所以最高次项约没了,因此得证。
回到题目,当前数列的通项公式为 ,他的一阶差分的通项公式为
发现是一个 次式,所以原始数列的通项公式为 次。
所以我们可以先构造 个点(直接暴力构造就行),然后使用拉格朗日插值。
考虑到基本公式 , 发现 都是连续的,所以
- 分母上为 ,发现为
注意需要判断符号如果 如果为奇数需要再乘 。 - 分子用一个前后缀维护就行。
code
#include<bits/stdc++.h>
#define N 1000010
#define int long long
#define mod 1000000007
using namespace std;
int n, k, pre[N], suc[N], frac[N], y = 0, ans = 0;
int fast(int a, int p){
int s = 1;
while(p){
if(p & 1) s = s * a % mod;
a = a * a % mod;
p = p >> 1;
}
//cout << s << endl;
return s;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> n >> k;
pre[0] = 1ll, suc[k + 3] = 1ll, frac[0] = 1ll;
for(int i = 1; i <= k + 2; i++) frac[i] = frac[i - 1] * i % mod;
for(int i = 1; i <= k + 2; i++) pre[i] = pre[i - 1] * (n - i) % mod;
for(int i = k + 2; i >= 1; i--) suc[i] = suc[i + 1] * (n - i) % mod;
for(int i = 1; i <= k + 2; i++){
y = (y + fast(i, k)) % mod;
int a = pre[i - 1] * suc[i + 1] % mod;
int b = frac[i - 1] * frac[k + 2 - i] % mod * ((k - i) & 1 ? -1ll : 1ll) % mod;
ans = (ans + a % mod * fast(b, mod - 2) % mod * y % mod) % mod;
}
cout << (ans + mod) % mod;
return 0;
}
``cpp
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】