zoukankan      html  css  js  c++  java
  • [CF438E] 小朋友和二叉树

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

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

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

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

    解得

    [f(x)=frac{1plusmnsqrt{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
    ",(ans[i]*2%MOD+MOD)%MOD);
        return false;
      }
    }
    int main(){
      return Patchouli::QAQ();
    }
    
  • 相关阅读:
    linux centos 8 为.net core 添加进程守护 Supervisor
    vue-quill-editor安装及使用:自定义工具栏和自定义中文字体,把字体写在html的style中
    nginx参数
    k8s pod 挂载glusterfs报错
    Vue跨域问题解决
    CSS导航菜单(二级菜单)
    CSS导航菜单(一级菜单)
    微信小程序开发正常,真机预览模式错误
    uniapp获取用户OpenId及用户详情
    uniapp 获取用户手机号
  • 原文地址:https://www.cnblogs.com/oiertkj/p/12245736.html
Copyright © 2011-2022 走看看