背景:
这个东西推了好久才学(被网上的神图吓到了)。
题目传送门:
https://www.luogu.org/problemnew/show/P4781
题意:
现在有一条过
n
n
n个点的函数,询问其在
x
x
x时的函数值
y
y
y。
正题:
y = f ( x ) = ∑ i = 0 n − 1 y i ∏ j = 0 , j ≠ i n − 1 x − x j x i − x j y=f(x)=\sum_{i=0}^{n-1}y_i\prod_{j=0,j≠i}^{n-1}\frac{x-x_j}{x_i-x_j} y=f(x)=i=0∑n−1yij=0,j̸=i∏n−1xi−xjx−xj
证明:
以下引自:https://blog.csdn.net/linjiayang2016/article/details/87877024。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define mod 998244353
using namespace std;
int n;
LL k;
struct node{LL x,y;} a[2010];
LL dg(LL x,LL k)
{
if(!k) return 1;
LL op=dg(x,k>>1);
if(k&1) return op*op%mod*x%mod; else return op*op%mod;
}
LL inv(LL x)
{
return dg(x,mod-2);
}
LL lagrange(LL x)
{
LL sum=0;
for(int i=0;i<n;i++)
{
LL op1=a[i].y,op2=1;
for(int j=0;j<n;j++)
{
if(i==j) continue;
op1=op1*((x-a[j].x+mod)%mod)%mod;
op2=op2*((a[i].x-a[j].x+mod)%mod)%mod;
}
sum=(sum+op1*inv(op2)%mod)%mod;
}
return sum;
}
int main()
{
scanf("%d %lld",&n,&k);
for(int i=0;i<n;i++)
scanf("%lld %lld",&a[i].x,&a[i].y);
printf("%lld",lagrange(k));
}
优化:
如果问题是动态加点,加点的过程中查询当前函数图像在
x
x
x位置的取值
y
y
y。
显然用刚才的做法是
Θ
(
n
3
)
\Theta(n^3)
Θ(n3)的。
我们要探寻更优秀的做法。
其实就是重心拉格朗日插值。
以下引自:https://blog.csdn.net/linjiayang2016/article/details/87877024。
总时间复杂度为
Θ
(
n
2
)
\Theta(n^2)
Θ(n2)。
貌似没有什么用,先不打了,等到遇到了再说。