Luogu4781 【模板】拉格朗日插值

原题链接:https://www.luogu.org/problemnew/show/P4781

拉格朗日插值

题目背景

这是一道模板题

题目描述

由小学知识可知, n 个点 ( x i , y i ) 可以唯一地确定一个多项式。

现在,给定 n 个点,请你确定这个多项式,并将 k 代入求值。

求出的值对 998244353 取模。

输入输出格式
输入格式:

第一行两个正整数 n , k ,含义如题。

接下来 n 行,每行两个正整数 x i , y i ,含义如题。

输出格式:

一个整数表示答案

输入输出样例
输入样例#1:

3 100
1 4
2 9
3 16

输出样例#1:

10201

输入样例#2:

3 100
1 1
2 2
3 3

输出样例#2:

100

说明

n 2000 x i , y i , k 998244353

样例一中的三个点确定的多项式是 f ( x ) = x 2 + 2 x + 1 ,将 100 代入求值得到 10201

样例二中的三个点确定的多项式是 f ( x ) = x ,将 100 代入求值得到 100

如果你不会拉格朗日插值,你可以到这里去学习一下。

此外,请注意算法的常数问题,建议开启O2优化。

题解

所谓 l a g r a n g e 插值法核心就是下面的公式,我们可以通过这个公式求出唯一的一个 n 1 阶多项式,使得多项式的函数图像经过给定的 n 个点:

f ( x ) = i = 1 n y i j = 1 , j i n x x j x i x j

这个式子看起来非常复杂,实际上本质非常简明,设 g ( x ) = j = 1 , j i n x x j x i x j ,就有 g ( x j ) = 0 , g ( x i ) = 1 ,实际上其他的 x 都会被消掉,只有 g ( x i ) 才有值,所以这个多项式表示的函数图像能经过给出的所有点。

唯一性的证明:通过待定系数法列出方程后,系数矩阵是范德蒙德矩阵,存在逆矩阵,因而解具有唯一性。

l a g r a n g e 插值法告诉我们: n 个点可以确定一个唯一的项数不超过点数的多项式,这一点非常重要,这种用点描述多项式的形式称为多项式的点值形式,从点值变成系数式的过程称为插值。

对于这道题来说,我们就不需要一一算出每一项的系数,只需要把 k 代入 f ( x ) ,按照公式枚举一下 i , j 就能在 O ( n 2 ) 的时间内算出 f ( k ) 的值。

代码
#include<bits/stdc++.h>
using namespace std;
const int M=2e4+5,mod=998244353;
int n,k,x[M],y[M];
void in(){scanf("%d%d",&n,&k);for(int i=1;i<=n;++i)scanf("%d%d",&x[i],&y[i]);}
int power(int a,int p){if(p==1)return a;int hh=power(a,p/2);return (p&1)?1ll*hh*hh%mod*a%mod:1ll*hh*hh%mod;}
int lagrange(int n,int k)
{
    int ans=0,s1,s2;
    for(int i=1;i<=n;++i)
    {
        s1=s2=1;
        for(int j=1;j<=n;++j){if(i==j)continue;s1=1ll*s1*(k-x[j])%mod;s2=1ll*s2*(x[i]-x[j])%mod;}
        ans=(ans+1ll*y[i]*s1%mod*power(s2,mod-2))%mod;
    }
    return ans<0?ans+mod:ans;
}
void ac(){printf("%d",lagrange(n,k));}
int main(){in();ac();}

猜你喜欢

转载自blog.csdn.net/shadypi/article/details/81239282