题解 P5158【【模板】多项式快速插值】
题意
给出 次多项式 的 个点值 ,求出这个多项式 。
。
思路
:更改了代码与部分说明。
以下默认 。
回顾拉格朗日插值的式子:
将后面的分母提到前面:
设 ,则:
容易分治 求出,然后使用多点求值求出 ,不会多点求值可以看这里。
接下来直接分治 即可。具体地,设 , 为 插出来的多项式,即 ,不难导出:
每一步的时间复杂度均为 ,于是总时间复杂度为 。
核心代码:
namespace Interpolation{
#define ls (rt<<1)
#define rs (rt<<1|1)
inline Poly MulT(const Poly &a,const Poly &b){
Poly F=a,G=b;
int n=a.size(),m=b.size();
reverse(G.begin(),G.end());
init(n);
F.resize(lim),G.resize(lim);
NTT(F,1),NTT(G,1);
for(int i=0;i<lim;i++)
G[i]=1ll*F[i]*G[i]%mod;
NTT(G,-1);
for(int i=m-1;i<n;i++)
F[i-m+1]=G[i];
F.resize(max(0,n-m+1));
return F;
}
Poly TR[N],T[N];
Poly Q,QY,ans;
inline void build(int rt,int l,int r){
if(l==r){
TR[rt]=(Poly){1,dec(0,Q[l])};
T[rt]=TR[rt],reverse(T[rt].begin(),T[rt].end());
return ;
}
int mid=l+r>>1;
build(ls,l,mid),build(rs,mid+1,r);
TR[rt]=TR[ls]*TR[rs];
T[rt]=TR[rt],reverse(T[rt].begin(),T[rt].end());
}
inline void solve(int rt,int l,int r,Poly F){
if(l==r){
ans[l]=F[0];
return ;
}
int mid=l+r>>1;
solve(ls,l,mid,MulT(F,TR[rs]));
solve(rs,mid+1,r,MulT(F,TR[ls]));
}
inline Poly solve(int rt,int l,int r){
if(l==r)
return (Poly){1ll*QY[l]*qpow(ans[l],mod-2)%mod};
int mid=l+r>>1;
Poly L=solve(ls,l,mid),R=solve(rs,mid+1,r);
return L*T[rs]+R*T[ls];
}
inline Poly solve(Poly X,Poly Y){
Q=X,QY=Y;
int n=X.size();
build(1,0,n-1);
Poly F=Deriv(T[1]);
ans.resize(n),F.resize(n*2);
solve(1,0,n-1,MulT(F,Inv(TR[1])));
return solve(1,0,n-1);
}
}
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下