• 分治FFT/NTT 模板


    题目要我们求$f[i]=sumlimits_{j=1}^{i}f[i-j]g[j];mod;998244353$

    直接上$NTT$肯定是不行的,我们不能利用尚未求得的项卷积

    所以要用$CDQ$分治,先递归$[l,mid]$,然后处理$[l,mid]$对$[mid+1,r]$的影响,再递归$[mid+1,r]$

    当我们处理$[l,mid]$对$[mid+1,r]$的影响时,$f[i](iin [l,mid])$的是已经求完的,所以能用$NTT$卷积

    细节比较多,注意不要让$f[i](iin [mid+1,r])$进入卷积,因为这时的$f[i]$还没有求完,会让后面的答案错误,所以要另外开一个数组记录答案

      1 #include <cmath>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #define N1 (1<<17)+10
      6 #define ll long long
      7 #define dd double
      8 #define inf 0x3f3f3f3f
      9 using namespace std;
     10 
     11 const ll p=998244353;
     12 void exgcd(ll a,ll b,ll &x,ll &y)
     13 {
     14     if(!b){ x=1; y=0; return; }
     15     exgcd(b,a%b,x,y); ll t=x; x=y; y=t-a/b*y;
     16 }
     17 ll qpow(ll x,ll y,const ll &mod)
     18 {
     19     ll ans=1;
     20     while(y){
     21         if(y&1) ans=ans*x%mod;
     22         x=x*x%mod; y>>=1;
     23     }return ans;
     24 }
     25 int gint()
     26 {
     27     int ret=0,fh=1;char c=getchar();
     28     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
     29     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
     30     return ret*fh;
     31 }
     32 int r[19][N1];
     33 ll A[N1],B[N1],C[N1],g[N1],f[N1],ret[N1],invl[N1],mulwn[N1],invwn[N1];
     34 void Pre(int len,int L)
     35 {
     36     int i,j;ll inv,invy;
     37     for(j=1;j<=L;j++) for(i=0;i<(1<<j);i++) 
     38         r[j][i]=(r[j][i>>1]>>1)|((i&1)<<(j-1)); 
     39     for(i=2;i<=len;i<<=1) 
     40     {
     41         mulwn[i]=qpow(3,(p-1)/i,p); 
     42         exgcd(mulwn[i],p,inv,invy); invwn[i]=(inv%p+p)%p;
     43         exgcd(i,p,inv,invy); invl[i]=(inv%p+p)%p;
     44     }
     45 }
     46 void NTT(ll *s,int len,int type,int L)
     47 {
     48     int i,j,k,inv; ll w,wn,t;
     49     for(i=0;i<len;i++) 
     50         if(i<r[L][i]) swap(s[i],s[r[L][i]]);
     51     for(k=2;k<=len;k<<=1)
     52     {
     53         wn=type>0?mulwn[k]:invwn[k];
     54         for(i=0;i<len;i+=k)
     55         {
     56             for(j=0,w=1;j<(k>>1);j++,w=w*wn%p)
     57             {
     58                 t=w*s[i+j+(k>>1)]%p;
     59                 s[i+j+(k>>1)]=(s[i+j]-t+p)%p;
     60                 s[i+j]=(s[i+j]+t)%p;
     61             }
     62         }
     63     }
     64     if(type==-1)
     65     for(i=0;i<len;i++)
     66         s[i]=s[i]*invl[len]%p;
     67 }
     68 void NTT_Main(int len,int L)
     69 {
     70     NTT(A,len,1,L); NTT(B,len,1,L);
     71     for(int i=0;i<len;i++) C[i]=A[i]*B[i]%p;
     72     NTT(C,len,-1,L);
     73 }
     74 ll de(int x)
     75 {
     76     ll ans=0;
     77     for(int i=1;i<=x;i++)
     78         (ans+=g[i]*f[x-i]%p)%=p;
     79     return ans;
     80 }
     81 int debug;
     82 void CDQ(int l,int r,int L)
     83 {
     84     if(l==r){ ret[l]=f[l]; return; }
     85     int mid=(l+r)>>1,i;
     86     CDQ(l,mid,L-1);
     87     if(l==0&&r==7) 
     88         debug=1;
     89     for(i=l;i<=r;i++) A[i-l]=ret[i],B[i-l]=g[i-l];
     90     NTT_Main(r-l+1,L);
     91     for(i=mid+1;i<=r;i++) (f[i]+=C[i-l])%=p;
     92     CDQ(mid+1,r,L-1);
     93 }
     94 
     95 int n,m,len,L;
     96 int main()
     97 {
     98     freopen("t2.in","r",stdin);
     99     scanf("%d",&n); int i; f[0]=1;
    100     for(i=1;i<n;i++) g[i]=gint(); 
    101     for(len=1,L=0;len<n;len<<=1,L++);
    102     Pre(len,L);
    103     CDQ(0,len-1,L);
    104     for(i=0;i<n;i++) printf("%lld ",f[i]);
    105     puts("");
    106     return 0;
    107 }
  • 相关阅读:
    Codeforces Round #388 (Div. 2)
    Codeforces Round #388 (Div. 2)
    Codeforces Round #388 (Div. 2)
    FZU 1914 单调队列
    ACM学习历程—POJ 3764 The xor-longest Path(xor && 字典树 && 贪心)
    ACM学习历程—SGU 275 To xor or not to xor(xor高斯消元)
    ACM学习历程—CSU 1216 异或最大值(xor && 贪心 && 字典树)
    ACM学习历程—HDU 5512 Pagodas(数学)
    ACM学习历程—HDU5521 Meeting(图论)
    ACM学习历程—HDU1030 Delta-wave(数学)
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10300591.html
Copyright © 2020-2023  润新知