• 真的分治fft


    以前学的分治fft f[i]=sigma(f[i-x]*g[x]),其中g[x]已知

    那么我们可以用cdq分治来做(l,mid 对mid+1,t的影响

    而现在的$f[i]=sum(f(i-x)*f(x))$

    我们如果沿用刚才的方法 会发现有$f(t-h)$这一项

    而$t-h>mid$是有可能的

    所以我们要在后续处理这件事情

    先将$f[l,mid]*f[l,mid]$乘起来

    如果$t-h<h$ 还要算$f[1,t-h]*f[h,mid]$ 注意还要乘2

    注意多次用fft 每次还原a,b数组 因为那个n是要比m大的,所以只清空到m的0是有问题的

    1e5的数据开O2要2s 预料之中了

    #include <bits/stdc++.h>
    using namespace std;
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (rint i=h;i<=t;i++)
    #define dep(i,t,h) for (rint i=t;i>=h;i--) 
    struct cp{
      double a,b;
    };
    const int N=3e5+5;
    int n,m,l,r[N],f[N];
    int a[N],b[N],w[N],G=3;
    const int mo=998244353;
    const int p=mo;
    IL int fsp(rint x,rint y)
    {
      rint ans=1;
      while (y)
      {
        if (y&1) ans=(1ll*ans*x)%mo;
        x=(1ll*x*x)%mo; 
        y>>=1;
      }
      return ans;
    }
    void fft(int *a,int o)
    {
        for (int i=0;i<n;i++)
          if (i>r[i]) swap(a[i],a[r[i]]);
        for (rint i=1;i<n;i*=2)
        {
            rint wn=fsp(G,(p-1)/(i*2)); w[0]=1;
            rep(j,1,i-1) w[j]=(1ll*w[j-1]*wn)%p;
            for (rint j=0;j<n;j+=(i*2))
            {
                rint *x=a+j,*y=a+i+j;
                for (rint k=0;k<i;k++)
                {
                    const int t=(1ll*w[k]*y[k])%p;
                    y[k]=x[k]-t;
                    if (y[k]<0) y[k]+=p;
                    if (y[k]>p) y[k]-=p;
                    x[k]=x[k]+t;
                    if (x[k]>p) x[k]-=p;
                }
            }
        }
        if (o==-1)
        {
          reverse(&a[1],&a[n]);
          for (int i=0,inv=fsp(n,p-2);i<n;i++)
            a[i]=1ll*a[i]*inv%p;
        }
    }
    void query()
    {
        l=0;
        for (n = 1; n <= m; n <<= 1) l++;
        for (int i=0;i<n;i++) r[i]=(r[i/2]/2)|((i&1)<<(l-1));
        fft(a,1),
        fft(b,1);
        for (int i=0;i<n;i++) a[i]=1ll*a[i]*b[i]%p;
        fft(a,-1);
    }
    #define mid ((h+t)/2)
    IL void js(rint &x,rint y)
    {
      x+=y;
      x%=mo;
    }
    void cdq_fz(int h,int t)
    {
      if (h==t) return;
      cdq_fz(h,mid);
      if (t-h<h)
      {
        n=m=t-h+(mid-h+1);
        rep(i,1,t-h) a[i-1]=f[i];
        rep(i,h,mid) b[i-h]=f[i];
        query();
        rep(i,mid+1,t) 
          if (i-h-2>=0) js(f[i],(2*a[i-h-2])%mo);
        rep(i,0,n) a[i]=b[i]=0;
      }
      n=m=2*(mid-h+1);
      rep(i,h,mid) a[i-h]=b[i-h]=f[i];
      query();
      rep(i,mid+1,t)
        if (i-(2*h+1)>=0) js(f[i],a[i-(2*h+1)]);
      rep(i,0,n) a[i]=b[i]=0;
      cdq_fz(mid+1,t);
    }
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      ios::sync_with_stdio(false);
      int k;
      cin>>k;
      f[1]=1; f[2]=1;
      cdq_fz(1,k);
      cout<<f[k]<<endl;
      return 0; 
    }

    对拍

    #include <bits/stdc++.h>
    using namespace std;
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    const int mo=998244353;
    int f[1100];
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("2.out","w",stdout);
      ios::sync_with_stdio(false);
      int n;
      cin>>n;
      f[1]=1; f[2]=1;
      rep(i,3,n)
        rep(k,1,i-2)
          f[i]+=(1ll*f[k]*f[i-k-1])%mo,f[i]%=mo; 
      cout<<f[n]<<endl;
      return 0;
    }

    还有说多项式右移

    f=f*f>>1+g

  • 相关阅读:
    构建之法阅读笔记一
    android studio的安装以及配置
    github本地上传口令
    注册git hub
    易用性
    第六周学习总结
    大型分布式网站架构设计与实践阅读笔记(3)
    第五周学习总结
    大型分布式网站架构设计与实践阅读笔记(2)
    第四周学习总结
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9570533.html
Copyright © 2020-2023  润新知