LOJ #165. 拉格朗日插值

重心拉格朗日插值模板题。

用上面那篇文章的公式计算。插入时更新每个 (w_i),询问时分别 (O(n)) 计算 (l(k))(sumlimits_{i=1}^n frac{w_i}{k-x_i}) 即可。注意使用上述公式时 (k-x_i) 不能为 (0),所以我们要特判 (k=x_i) 的情况。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define int long long

using namespace std;

const int N=3009,M=998244353;
int n,cnt,x[N],y[N],w[N];

void init()
{
	scanf("%lld",&n);
}

int ksm(int a,int b)
{
	int res=1;
	while(b)
	{
		if(b&1)
			res=res*a%M;
		b>>=1,a=a*a%M;
	}
	return res;
}

void work()
{
	int opt,X,Y;
	while(n--)
	{
		scanf("%lld",&opt);
		if(opt==1)
		{
			scanf("%lld %lld",&X,&Y);
			x[++cnt]=X,y[cnt]=w[cnt]=Y;
			for (int i=1;i<cnt;i++)
				w[i]=w[i]*ksm(x[i]-x[cnt],M-2)%M,
				w[cnt]=w[cnt]*ksm(x[cnt]-x[i],M-2)%M;
		}
		else
		{
			scanf("%lld",&X);
			int flag=0;
			for (int i=1;i<=cnt;i++)
				if(X==x[i])
				{
					flag=1,printf("%lld
",y[i]);
					break;
				}
			if(flag) continue;
			int tmp=1,_tmp=0;
			for (int i=1;i<=cnt;i++)
				tmp=tmp*(X-x[i])%M;
			for (int i=1;i<=cnt;i++)
				_tmp=(_tmp+w[i]*ksm(X-x[i],M-2)%M)%M;
			printf("%lld
",(tmp*_tmp%M+M)%M);
		}
	}
}

signed main()
{
	init();
	work();
	return 0;
}

原文地址:https://www.cnblogs.com/With-penguin/p/13510369.html