• 拉格朗日插值


    拉 格 朗 日 插 值 法 可 构 造 一 个 经 过 任 意 n 个 点 ( a 1 , b 1 ) , ( a 2 , b 2 ) , ( a 3 , b 3 ) , … , ( a n , b n ) 的 函 数 f , 设 f = f 1 + f 2 + ⋯ + f n , 需 要 让 f 1 , f 2 , … , f n 均 经 过 这 n 个 点 , 且 当 x = a i 时 , f i = b i ; 当 x = a j ( j ≠ i ) 时 , f i = 0. 拉格朗日插值法可构造一个经过任意n个点(a_1,b_1),(a_2,b_2),(a_3,b_3),dots,(a_n,b_n)的函数f,设f=f_1+f_2+dots+f_n,需要让f_1,f_2,dots,f_n均经过这n个点,且当x=a_i时,f_i=b_i;当x=a_j(j e i)时,f_i=0. n(a1,b1),(a2,b2),(a3,b3),,(an,bn)f,f=f1+f2++fn,f1,f2,,fnn,x=ai,fi=bi;x=aj(j=i),fi=0.

    那 么 显 然 , 由 f 1 , f 2 , … , f n 相 加 得 到 的 的 f , 恰 好 经 过 了 a 1 , a 2 , … , a n . 那么显然,由f_1,f_2,dots,f_n相加得到的的f,恰好经过了a_1,a_2,dots,a_n. ,f1,f2,,fnf,a1,a2,,an.
    f 1 , f 2 , … , f n 被 称 为 拉 格 朗 日 基 函 数 , 表 达 式 为 : f i = b i ∏ j ≠ i x − x j x i − x j f_1,f_2,dots,f_n被称为拉格朗日基函数,表达式为:f_i=b_iprod_{j e i} frac {x-x_j} {x_i-x_j} f1,f2,,fn,:fi=bij=ixixjxxj

    那 么 , 由 拉 格 朗 日 插 值 法 得 到 的 函 数 f 的 表 达 式 为 : ∑ i = 1 n b i ∏ j ≠ i x − x j x i − x j , 时 间 复 杂 度 为 O ( n 2 ) . 那么,由拉格朗日插值法得到的函数f的表达式为:sum_{i=1}^{n}b_iprod_{j e i} frac{x-x_j} {x_i-x_j},时间复杂度为O(n^2). ,f:i=1nbij=ixixjxxj,O(n2).

    若 在 程 序 实 现 中 , 每 一 次 计 算 x i − x j 值 时 都 求 一 次 其 的 乘 法 逆 元 , 时 间 复 杂 度 将 乘 上 l o g   n , 我 们 选 择 先 计 算 所 有 x i − x j 的 乘 积 , 再 求 逆 元 . 若在程序实现中,每一次计算x_i-x_j值时都求一次其的乘法逆元,时间复杂度将乘上log n,我们选择先计算所有x_i-x_j的乘积,再求逆元. ,xixj,log n,xixj,.

    另外,此处求逆元必须选择快速幂方法,否则你将陷入深深的迷惑中.为什么呢?在此题中,可能会需要求负数的逆元,但根据辗转相除法求负数和-1的最大公约数时,求得的最大公约数为-1(在cmath库函数__gcd中计算也会得到-1,可见其运用的是辗转相除法).可是在数学定义上,gcd(a,b)=gcd(|a|,|b|),也就是说负数和-1的最大公约数为1.贝祖等式ax+by=gcd(a,b)的gcd(a,b)显然是数学定义上的.那么便不能得到ax+by=1,或者说我们算的其实是ax+by=-1,完全错误了.(我在这个问题上困扰了接近1个小时TAT)

    代码:

    #include <bits/stdc++.h>
    #define ll long long
    
    using namespace std;
    ll n,k,x[2005],y[2005],mod=998244353,ans;//998244353是个题目常用取模质数 
    
    ll fpm(ll x,ll power,ll mod) 
    {
        x %= mod;
        ll ans = 1;
        for (; power; power >>= 1,(x*=x)%=mod)
        	if(power&1) (ans*=x)%=mod;
        return ans;
    }
    
    ll inv(ll x)
    {
    	return fpm(x,mod-2,mod);
    }
    
    int main()
    {
    	cin>>n>>k;
    	for(int i=1;i<=n;i++)
    	{
    		cin>>x[i]>>y[i];
    	}
    	for(int i=1;i<=n;i++)
    	{
    		ll ans_up=y[i],ans_down=1;
    		for(int j=1;j<=n;j++)
    		{
    			if(j==i) continue;
    			ans_up=(ans_up*(k-x[j]))%mod;
    			ans_down=(ans_down*(x[i]-x[j]))%mod;
    		}
    		ans=(ans+(ans_up*inv(ans_down)))%mod;
    	}
    	cout<<(ans+mod)%mod<<endl;
    	
    	return 0;
    }
    
  • 相关阅读:
    命令模式
    单例模式
    装饰者模式
    监听者模式
    三角形三心和特点
    u3d中texture2D的Advanced设置解析
    c# 三种常见的委托
    c# float显示时保存一位小数
    Jakarta Java Mail属性参数配置
    SpringDataRedis的Keyspaces设置
  • 原文地址:https://www.cnblogs.com/huaruoji/p/14425570.html
Copyright © 2020-2023  润新知