• LGP5667 拉格朗日插值2


    题目

    套一下拉格朗日插值的公式

    [egin{aligned} f(m+k)&=sum_{i=0}^nf(i)prod_{i eq j}frac{m+k-j}{i-j}\ &=sum_{i=0}^nfrac{f(i)}{i!(n-i)!(-1)^{n-i}}frac{(m+k)^{underline{n+1}}}{(m+k-i)}\ &=(m+k)^{underline{n+1}}sum_{i=0}^nfrac{f(i)}{i!(n-i)!(-1)^{n-i}} imes frac{1}{m+k-i} end{aligned} ]

    不难看到(k-i)(i)(k),于是这是一个卷积的形式

    构造两个函数

    [a_i=frac{f(i)}{i!(n-i)!(-1)^{n-i}},b_i=frac{1}{m+i} ]

    但是这个(b)可能有负下标,我们平移一个(n)就好了

    代码

    #include<bits/stdc++.h>
    #define re register
    const int mod=998244353;
    const int G[2]={3,(mod+1)/3};
    const int maxn=6e5+5;
    int n,m,len,a[maxn],b[maxn],rev[maxn],fac[maxn],ifac[maxn];
    inline int dqm(int x) {return x<0?x+mod:x;}
    inline int qm(int x) {return x>=mod?x-mod:x;}
    inline int ksm(int a,int b) {
    	int S=1;for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)S=1ll*S*a%mod;return S;
    }
    inline void NTT(int *f,int o) {
    	for(re int i=0;i<len;i++)if(i<rev[i])std::swap(f[i],f[rev[i]]);
    	for(re int i=2;i<=len;i<<=1) {
    		int ln=i>>1,og1=ksm(G[o],(mod-1)/i);
    		for(re int t,og=1,l=0;l<len;l+=i,og=1)
    			for(re int x=l;x<l+ln;++x) {
    				t=1ll*og*f[x+ln]%mod,og=1ll*og*og1%mod;
    				f[x+ln]=dqm(f[x]-t);f[x]=qm(f[x]+t);
    			}
    	}
    	if(!o)return;int Inv=ksm(len,mod-2);
    	for(re int i=0;i<len;i++) f[i]=1ll*f[i]*Inv%mod;
    }
    int main() {
    	scanf("%d%d",&n,&m);for(re int i=0;i<=n;i++)scanf("%d",&a[i]);
    	fac[0]=ifac[0]=1;for(re int i=1;i<=n;i++)fac[i]=1ll*fac[i-1]*i%mod;
    	ifac[n]=ksm(fac[n],mod-2);for(re int i=n-1;i;--i)ifac[i]=1ll*ifac[i+1]*(i+1)%mod;
    	for(re int i=0;i<=n+n;i++) b[i]=ksm(m+i-n,mod-2);
    	for(re int i=0;i<=n;i++) a[i]=1ll*a[i]*ifac[i]%mod*ifac[n-i]%mod;
    	for(re int i=0;i<=n;i++) if((n-i)&1) a[i]=dqm(-a[i]);
    	len=1;while(len<=n+n+n) len<<=1;
    	for(re int i=0;i<len;i++) rev[i]=rev[i>>1]>>1|((i&1)?len>>1:0);
    	NTT(a,0),NTT(b,0);
    	for(re int i=0;i<len;i++) a[i]=1ll*a[i]*b[i]%mod;
    	NTT(a,1);int nw=1;
    	for(re int i=m;i>=m-n;--i) nw=1ll*nw*i%mod;
    	for(re int i=0;i<=n;i++) {
    		printf("%d ",1ll*a[i+n]*nw%mod);
    		nw=1ll*nw*ksm(m+i-n,mod-2)%mod;
    		nw=1ll*nw*(m+i+1)%mod;
    	}
    	return 0;
    }
    
  • 相关阅读:
    数组中的每一个对象执行一次方法:makeObjectsPerformSelector
    $.each() each
    JQ js选择节点操作
    Sublime Text 3 快捷键
    TotoiseSVN的基本使用方法
    Hbuilder快捷键
    获取网页内容区域各种高/宽汇总
    TP操作
    xhr接收php://output的二进制文件,并转换成excel表格
    Go语言的%d,%p,%v等占位符的使用
  • 原文地址:https://www.cnblogs.com/asuldb/p/12120063.html
Copyright © 2020-2023  润新知