拉格朗日插值

​  给你(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_iprod_{j=1,j eq i}^nfrac{x-x_j}{x_i-x_j}=sum_{i=1}^ny_ifrac{x-x_1}{x_i-x_1}cdotsfrac{x-x_{i-1}}{x_i-x_{i-1}}frac{x-x_{i+1}}{x_i-x_{i+1}}cdotsfrac{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}cdotsfrac{x-x_{i-1}}{x_i-x_{i-1}}frac{x-x_{i+1}}{x_i-x_{i+1}}cdotsfrac{x-x_n}{x_i-x_n}=egin{cases} 1~~~~(x=x_i)\0~~~~(x=x_j,j eq i)end{cases} ]

​  因为当(x=x_i)时每一项的分子都等于分母,当(x=x_j(j eq 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;
	}
}
原文地址:https://www.cnblogs.com/ywwyww/p/8511166.html