• 并不对劲的拉格朗日插值


    题目大意

    (n)(nleq 2000))个点((x_1,y_1),...,(x_n,y_n))((x,yleq 998244353)),求多项式(f(x))使(forall iin [1,n],f(x_i) mod 998244353=y_i)

    题解

    结论:(f(x)=sumlimits_{i=1}^{n}y_ifrac{prodlimits_{j=1,j eq i}^{n}(x-x_j)}{prodlimits_{j=1,j eq i}^{n}(x_i-x_j)})
    该式可以保证当(x=x_k)时,(i=k)(frac{prodlimits_{j=1,j eq i}^{n}(x-x_j)}{prodlimits_{j=1,j eq i}^{n}(x_i-x_j)}=1)(i eq k)(frac{prodlimits_{j=1,j eq i}^{n}(x-x_j)}{prodlimits_{j=1,j eq i}^{n}(x_i-x_j)}=0),符合题目要求。
    考虑怎么求(f(x))每一项系数。
    (f(x)=sumlimits_{i=1}^{n}frac{y_i}{prodlimits_{j=1,j eq i}^{n}(x_i-x_j)} imes(prodlimits_{j=1,j eq i}^{n}(x-x_j)))
    前一部分可以直接求,对于后一部分(prodlimits_{j=1,j eq i}^{n}(x-x_j))
    先求出(g(x)=prodlimits_{j=1}^{n}(x-x_j)),即求出((x-x_1)(x-x_2)(x-x_3)...(x-x_n))(k)次项系数相当于在((-x_1),(-x_2),...,(-x_n))中选(n-k)个数的所有方案的积的和,这部分可以设(dp(i,j))表示考虑前(i)个数,选了(j)个数;
    接下来考虑如何从(g(x))中去掉((x-x_i))得到(prodlimits_{j=1j eq i}^{n}(x-x_j)),相当于已知(g(x),x_i),求(h(x))使(h(x) imes(x-x_i)=g(x)),设(g(x)=sumlimits_{j=0}^n a_j imes x^j)(h(x)=sumlimits_{j=0}^{n-1}b_j imes x^j),就有(sumlimits_{j=0}^{n-1}b_j imes x^{j+1}-sumlimits_{j=0}^{n-1}b_j imes x_j imes x^j=sumlimits_{j=0}^n a_j imes x^j),该式无论(x)取何值恒成立,就可以得出(x)对应次项的系数相等,即(b_0=-frac{a_0}{x_i})(forall jin[1,n],b_j=-frac{a_j-b_{j-1}}{x_i})
    时间复杂度(Theta(n^2))

    代码
    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<ctime>
    #include<iomanip>
    #include<iostream>
    #include<map>
    #include<queue>
    #include<set>
    #include<stack>
    #include<vector>
    #define rep(i,x,y) for(register int i=(x);i<=(y);++i)
    #define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
    #define view(u,k) for(int k=fir[u];~k;k=nxt[k])
    #define LL long long
    #define maxn 2007
    using namespace std;
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)&&ch!='-')ch=getchar();
        if(ch=='-')f=-1,ch=getchar();
        while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
        return x*f;
    }
    void write(int x)
    {
        if(x==0){putchar('0'),putchar('
    ');return;}
        int f=0;char ch[20];
        if(x<0)putchar('-'),x=-x;
        while(x)ch[++f]=x%10+'0',x/=10;
        while(f)putchar(ch[f--]);
        putchar('
    ');
        return;
    }
    const LL mod=998244353;
    int qx[maxn],qy[maxn],a[maxn],n,K,f[maxn];
    int mo(int x){return x>=mod?x-mod:x;}
    int mul(int x,int y){int res=1;while(y){if(y&1)res=(LL)res*x%mod;x=(LL)x*x%mod,y>>=1;}return res;}
    int getf(int x)
    {
        int ans=0,now=1;
        rep(i,0,n-1)ans=mo(ans+(LL)now*a[i]%mod),now=(LL)now*x%mod;
        return ans;
    }
    int main()
    {
        n=read(),K=read();
        rep(i,1,n)qx[i]=read(),qy[i]=read();
        f[0]=1;
        rep(i,1,n)dwn(j,i,1)
        	f[j]=mo(f[j]+(LL)f[j-1]*(mod-qx[i])%mod);
        reverse(f,f+n+1);
    	rep(i,1,n)
        {
        	int num=1,nyx=mul(mod-qx[i],mod-2);
        	rep(j,1,n)if(j!=i)num=(LL)num*mo(qx[i]-qx[j]+mod)%mod;
        	num=(LL)mul(num,mod-2)*qy[i]%mod;
    		int lst=0;
    		rep(j,0,n-1)
        	{
        		lst=(LL)mo(f[j]-lst+mod)*nyx%mod,a[j]=mo(a[j]+(LL)lst*num%mod);
        	}
        }
    	write(getf(K));
    	return 0;
    }
    
    一些感想

    终于填上这个坑了。。。

  • 相关阅读:
    《血战钢锯岭》影评
    座椅
    指示灯点亮/闪烁
    存钱大法
    加注燃油
    处理过热
    收入“三分法”
    请求文件
    规格
    处理瘪胎
  • 原文地址:https://www.cnblogs.com/xzyf/p/11592260.html
Copyright © 2020-2023  润新知