[CF438E] 小朋友和二叉树

多项式开根的板子题
因为忘了又去推了一次开根

每一个值的计算都要枚举左子树放多少,中间的点放多少,右子树放多少

不难看出式三个多项式卷积的形式,特殊的是\(f(0)=1\)

\[f(x)=a(x)*f^2(x)+1 \]

解得

\[f(x)=\frac{1\plusmn\sqrt{1-4a(x)}}{2a} \]

带个0舍掉一个解

\[f(x)=\frac{1-\sqrt{1-4a(x)}}{2a} \]

敲完之后发现输出的都是0,原因是这个分母常数项是0,不能求逆

我们进行分母无理化的迷惑操作

\[\frac{(1-\sqrt{1-4a(x)})(1+\sqrt{1+4a(x)})}{2a(1+\sqrt{1+4a(x)})} \]

\[\frac{4a}{2a(1+\sqrt{1+4a(x)})} \]

\[\frac{2}{1+\sqrt{1+4a(x)}} \]

然后就可以做了

#include<cstdio>
#include<algorithm>
using namespace std;
namespace Patchouli{
  const int N=414514;
  const int MOD=998244353;
  const int G=3;
  const int INV=332748118;
  const int INV2=499122177;
  long long tmp[N],res[N];
  long long f[N],g[N],ans[N];
  int limit,len,reverse[N];
  inline long long pow(long long x,int y){
    long long ans=1;
    while(y){
      if(y&1)ans=ans*x%MOD;
      x=x*x%MOD;
      y>>=1;
    }
    return ans;
  }
  inline void NTT(long long *f,int res){
    long long tx,ty,t,w;
    for(int i=0;i<limit;++i)
      if(i<reverse[i])
	swap(f[i],f[reverse[i]]);
    for(int i=1;i<limit;i<<=1){
      t=pow(res,(MOD-1)/(i<<1));
      for(int j=0;j<limit;j+=(i<<1)){
	w=1;
	for(int k=0;k<i;++k,w=w*t%MOD){
	  tx=f[j+k],ty=f[j+i+k]*w%MOD;
	  f[j+k]=(tx+ty)%MOD;
	  f[j+i+k]=(tx-ty)%MOD;
	}
      }
    }
    if(res==INV){
      long long inv=pow(limit,MOD-2);
      for(int i=0;i<limit;++i)
	f[i]=f[i]*inv%MOD;
    }
  }
  void inv(int n,long long *f,long long *g){
    if(n==1){
      g[0]=pow(f[0],MOD-2);
      return;
    }
    inv((n+1)>>1,f,g);
    limit=1,len=0;
    while(limit<(n<<1))
      limit<<=1,++len;
    for(int i=0;i<limit;++i)
      reverse[i]=(reverse[i>>1]>>1)|((i&1)<<(len-1));
    for(int i=0;i<n;++i)
      tmp[i]=f[i];
    for(int i=n;i<limit;++i)
      tmp[i]=0;
    NTT(tmp,G),NTT(g,G);
    for(int i=0;i<limit;++i)
      g[i]=(2-g[i]*tmp[i]%MOD)*g[i]%MOD;
    NTT(g,INV);
    for(int i=n;i<limit;++i)
      g[i]=0;
  }
  void sqrt(int n,long long *f,long long *g){
    if(n==1){
      g[0]=1;
      return;
    }
    sqrt((n+1)>>1,f,g);
    inv(n,g,res);
    limit=1,len=0;
    for(int i=0;i<limit;++i)
      reverse[i]=(reverse[i>>1]>>1)|((i&1)<<(len-1));
    while(limit<(n<<1))
      limit<<=1,++len;
    for(int i=0;i<n;++i)
      tmp[i]=f[i];
    for(int i=n;i<limit;++i)
      tmp[i]=0;
    NTT(g,G),NTT(tmp,G),NTT(res,G);
    for(int i=0;i<limit;++i)
      g[i]=(g[i]-(g[i]*g[i]-tmp[i])%MOD*INV2%MOD*res[i])%MOD;
    NTT(g,INV);
    for(int i=0;i<limit;++i)
      res[i]=0;
    for(int i=n;i<limit;++i)
      g[i]=0;
  }
  inline int read(){
    int a=1,b=0;char t;
    do{t=getchar();if(t=='-')a=-1;}while(t>'9'||t<'0');
    do{b=b*10-'0'+t;t=getchar();}while(t>='0'&&t<='9');
    return a*b;
  }
  int QAQ(){
    int n=read(),m=read()+1;
    for(int i=1;i<=n;++i)
      f[read()]=-4;
    f[0]+=1;
    sqrt(m,f,g);
    g[0]=1+g[0]%MOD;
    inv(m,g,ans);
    for(int i=1;i<m;++i)
      printf("%lld\n",(ans[i]*2%MOD+MOD)%MOD);
    return false;
  }
}
int main(){
  return Patchouli::QAQ();
}
posted @ 2020-01-31 16:18  蒟蒻TKJ  阅读(121)  评论(0编辑  收藏  举报