拉格朗日插值
给你\(n\)个点:\((x_1,y_1),(x_2,y_2),\ldots,(x_n,y_n)\),求经过这\(n\)个点的\(n-1\)次多项式\(L(x)\)
直接高斯消元是\(O(n^3)\)的。
\[L(x)=\sum_{i=1}^ny_i\prod_{j=1,j\neq i}^n\frac{x-x_j}{x_i-x_j}=\sum_{i=1}^ny_i\frac{x-x_1}{x_i-x_1}\cdots\frac{x-x_{i-1}}{x_i-x_{i-1}}\frac{x-x_{i+1}}{x_i-x_{i+1}}\cdots\frac{x-x_n}{x_i-x_n}
\]
设\(A(x)=\prod_{i=1}^n(x-x_i),B_i(x)=\frac{A(x)}{x-x_i},C_i(x)=\frac{B_i(x)}{B_i(x_i)}\)
可以看出
\[C_i(x)=\frac{x-x_1}{x_i-x_1}\cdots\frac{x-x_{i-1}}{x_i-x_{i-1}}\frac{x-x_{i+1}}{x_i-x_{i+1}}\cdots\frac{x-x_n}{x_i-x_n}=\begin{cases} 1~~~~(x=x_i)\\0~~~~(x=x_j,j\neq i)\end{cases}
\]
因为当\(x=x_i\)时每一项的分子都等于分母,当\(x=x_j(j\neq i)\)时有一项的分子为\(0\)。
那么
\[L(x)=\sum_{i=1}^n y_iC_i(x)
\]
这样就可以\(O(n^2)\)算出来了。
代码
\(t\)个点,插出\(t-1\)次多项式。
void solve()
{
memset(c,0,sizeof c);
c[0]=1;
memset(ans,0,sizeof ans);
for(i=1;i<=t;i++)
for(j=t;j>=0;j--)
{
(c[j+1]+=c[j])%=p;
(c[j]=-c[j]*x[i])%=p;
}
for(i=1;i<=t;i++)
{
memcpy(d,c,sizeof d);
memset(b,0,sizeof b);
for(j=t;j>=0;j--)
{
b[j]=d[j+1];
d[j]=(d[j]+d[j+1]*x[i])%p;
d[j+1]=0;
}
ll s=0,px=1;
for(j=0;j<=t;j++)
{
s=(s+px*b[j])%p;
px=px*x[i]%p;
}
s=fp(s,p-2)*y[i]%p;
for(j=0;j<=t;j++)
b[j]=b[j]*s%p;
for(j=0;j<=t;j++)
ans[j]=(ans[j]+b[j])%p;
}
}
\(n\)个点,求\(f(m)\)
void solve()
{
ll ans=0;
for(i=1;i<=n;i++)
{
ll s1=1,s2=1;
for(j=1;j<=n;j++)
if(j!=i)
{
s1=(s1*(m-x[j]))%p;
s2=(s2*(x[i]-x[j]))%p;
}
ans=(ans+y[i]*s1%p*fp(s2,p-2)%p)%p;
}
}