其实很简单。
考虑一个 k 次多项式,需要 k+1 个 x 值不同的点来确定。那现在要求构造一个函数 f(x) 过点 P1(x1,y1),P2(x2,y2),⋯,Pn(xn,yn)。我们设第 i 个点在 x 轴的投影是 P′i(xi,0)。
考虑构造 n 个函数 gi(x),使得对于函数 gi(x),过 P′j(xj,yj),j≠i 和 Pi(xi,yi)。即只在 (xi−1,xi+1) 区间有实际值。
那么可知,f(x)=n∑i=1gi(x)。既然让 ∀j≠i 都没值,那就设 gi(x)=a∏j≠i(x−xj),其中 a 是修正量,因为要满足 gi(xi)=yi。
带入 Pi(xi,yi) 可得:
a=yi∏j≠i(xi−xj)
带回 gi(x) 可得:
gi(x)=yi×∏j≠ix−xjxi−xj
带回 f(x) 可得:
f(x)=n∑i=1(yi×∏j≠ix−xjxi−xj)
然后这就是拉格朗日插值的形式。整体算的时间复杂度是 O(n2)。
模板代码:
| #include<bits/stdc++.h> |
| using namespace std; |
| #define int long long |
| const int N=2e3+3,mod=998244353; |
| int ppow(int a,int b) |
| { |
| int res=1; |
| while(b) |
| { |
| if(b&1) res=(res*a)%mod; |
| a=(a*a)%mod,b>>=1; |
| }return res; |
| } |
| int n,k; |
| int x[N],y[N]; |
| signed main() |
| { |
| cin>>n>>k; |
| int ans=0; |
| for(int i=1;i<=n;i++) cin>>x[i]>>y[i]; |
| for(int i=1;i<=n;i++) |
| { |
| int res1=1,res2=1; |
| for(int j=1;j<=n;j++) |
| { |
| if(i==j) continue; |
| res1=(res1*(k-x[j]+mod)%mod)%mod; |
| res2=(res2*(x[i]-x[j]+mod)%mod)%mod; |
| } |
| ans=(ans+y[i]*res1%mod*ppow(res2,mod-2)%mod)%mod; |
| } |
| cout<<ans; |
| } |
然后有一个比较神秘的问题,是说 n∑i=1ik 是一个 k+1 次多项式。
试着证明一下:
若它是一个 k+1 次多项式,那么它一定和另一个 k+1 次多项式有对等关系。我们将 ∑ni=1ik 记为 S(n,k)。
考虑将两个 k+1 次多项式 (n+1)k+1 和 nk+1 相减,可以得出:
(n+1)k+1−nk+1=k+1∑i=0(k+1i)ni−nk+1=k∑i=0(k+1i)ni⋯⋯⋯(1)
然后,将 nk+1 和 (n−1)k+1 相减,可以得出:
nk+1−(n−1)k+1=k+1∑i=0(k+1i)(n−1)i−(n−1)k+1=k∑i=0(k+1i)(n−1)i⋯⋯⋯(2)
以此类推,到最后,令 1k+1 和 0k+1 相减,是 k∑i=00i⋯⋯⋯(n+1)
这样,我们就有了 n+1 个式子,考虑将他们加起来,根据裂项相消法,n+1∑i=1(i)=(n+1)k+1。
另一侧:
(n+1)k+1=k+1∑i=0(k+1i)ni+k+1∑i=0(k+1i)(n−1)i+⋯+k∑i=00i=k+1∑i=0(k+1i)n∑j=0ji=k+1∑i=0(k+1i)S(n,i)
由此,不难得到 S(n,i) 和 (n+1)k+1 的关系,也就证明了这个结论。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析