• 【洛谷P4781】【模板】拉格朗日插值


    题目

    题目链接:https://www.luogu.com.cn/problem/P4781
    由小学知识可知 (n) 个点 ((x_i,y_i)) 可以唯一地确定一个多项式 (y = f(x))
    现在,给定这 (n) 个点,请你确定这个多项式,并求出 (f(k) mod 998244353) 的值。
    (1 le n leq 2 imes 10^3)(1 le x_i,y_i,k < 998244353)(x_i) 两两不同。

    思路

    给出一个 (n) 次多项式的点值,拉格朗日插值法可以在 (O(n^2)) 的时间内求出该多项式 (f(k)) 的值。
    为了插出该多项式,拉格朗日插值的思路是对每一个点值构建一个拉格朗日基本多项式,使得将 (x_1sim x_n) 带进去只有 (x_i) 的函数值是 (1),其余均为 (0)
    先不考虑如何构建多项式使得只有 (x_i) 带进去非 (0)。因为 (x_i) 两两不等,所以可以考虑如下多项式

    [prod_{j eq i}(k-x_j) ]

    显然只有当 (k=x_i) 的时候非 (0)。为了让其值为 (1),可以给每一项都除以 (x_i-x_j),此时再带入 (k=x_i) 多项式的值就是 (1cdot 1cdot 1cdots=1)
    所以说我们可以插出多项式

    [f(k)=sum_{i=1}^{n}y_iprod_{j eq i}frac{k-a_j}{x_i-x_j} ]

    当我们带入 (x_i) 时,多项式的函数值就是 (0+0+cdots+y_i+0+0+cdots)。这样我们就插出这个多项式了。
    时间复杂度 (O(n^2))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N=2010,MOD=998244353;
    int n,k;
    ll ans,x[N],y[N];
    
    ll fpow(ll x,ll k)
    {
    	ll ans=1;
    	for (;k;k>>=1,x=x*x%MOD)
    		if (k&1) ans=ans*x%MOD;
    	return ans;
    }
    
    int main()
    {
    	scanf("%d%d",&n,&k);
    	for (int i=1;i<=n;i++)
    		scanf("%lld%lld",&x[i],&y[i]);
    	for (int i=1;i<=n;i++)
    	{
    		ll res1=1,res2=1;
    		for (int j=1;j<=n;j++)
    			if (i!=j)
    			{
    				res1=res1*(k-x[j])%MOD;
    				res2=res2*(x[i]-x[j])%MOD;
    			}
    		ans=(ans+res1*fpow(res2,MOD-2)%MOD*y[i])%MOD;
    	}
    	printf("%lld",(ans%MOD+MOD)%MOD);
    	return 0;
    }
    
  • 相关阅读:
    n皇后问题
    hdu 4911 Inversion and poj2299 [树状数组+离散化]
    离散化
    汉诺塔
    hdu 4027 Can you answer these queries?[线段树]
    开根号
    hdu 1069 Monkey and Banana 【动态规划】
    Linux系统下安装rz/sz命令及使用说明
    PHP获得指定日期所在月的第一天和最后一天
    PHP获得指定日期所在星期的第一天和最后一天
  • 原文地址:https://www.cnblogs.com/stoorz/p/14406753.html
Copyright © 2020-2023  润新知