分治FFT

Posted nofind

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分治FFT相关的知识,希望对你有一定的参考价值。

一、处理的问题

给出多项式(g[0...n]),求出(f[0...n])满足(f_i=sumlimits_{j=1}^if_{i-j}g_j),边界(f_0=1)

我们发现这是个卷积的形式,但是不能直接(FFT),因为我们并不知道(f_{i-j}),于是考虑分治。

按照CDQ分治的方法,对于当前处理的区间([l,r]),我们先处理([l,mid]),之后考虑([l,mid])([mid+1,r])的贡献,写出来就是:(f_i+=sumlimits_{j=l}^{mid}f_j*g_{i-j})

模板题

code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
const int mod=998244353;
const int G=3;
const int invG=332748118;
int n,lim,len;
int f[maxn],g[maxn],tmp1[maxn],tmp2[maxn],pos[maxn];
inline int read()
{
    char c=getchar();int res=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
    return res*f; 
}
inline int power(int x,int k)
{
    int res=1;
    while(k)
    {
        if(k&1)res=1ll*res*x%mod;
        x=1ll*x*x%mod;k>>=1;
    }
    return res;
}
inline void NTT(int* a,int op)
{
    for(int i=0;i<lim;i++)if(i<pos[i])swap(a[i],a[pos[i]]);
    for(int l=1;l<lim;l<<=1)
    {
        int wn=power(op==1?G:invG,(mod-1)/(l<<1));
        for(int i=0;i<lim;i+=l<<1)
        {
            int w=1;
            for(int j=0;j<l;j++,w=1ll*w*wn%mod)
            {
                int x=a[i+j],y=1ll*w*a[i+l+j]%mod;
                a[i+j]=(x+y)%mod;a[i+l+j]=(x-y+mod)%mod;
            }
        }
    }
    if(op==1)return;
    int inv=power(lim,mod-2);
    for(int i=0;i<lim;i++)a[i]=1ll*a[i]*inv%mod;
}
void solve(int l,int r)
{
    if(l==r)return;
    int mid=(l+r)>>1;
    solve(l,mid);
    for(int i=l;i<=mid;i++)tmp1[i-l]=f[i],tmp2[i-l]=g[i-l];
    for(int i=mid+1;i<=r;i++)tmp1[i-l]=0,tmp2[i-l]=g[i-l];
    lim=1,len=0;
    while(lim<=r-l)lim<<=1,len++;
    for(int i=0;i<lim;i++)pos[i]=(pos[i>>1]>>1)|((i&1)<<(len-1));
    for(int i=r-l+1;i<lim;i++)tmp1[i]=tmp2[i]=0;
    NTT(tmp1,1);NTT(tmp2,1);
    for(int i=0;i<lim;i++)tmp1[i]=1ll*tmp1[i]*tmp2[i]%mod;
    NTT(tmp1,-1);
    for(int i=mid+1;i<=r;i++)f[i]=(f[i]+tmp1[i-l])%mod;
    solve(mid+1,r);
}
int main()
{
    n=read();
    for(int i=1;i<n;i++)g[i]=read();
    f[0]=1;
    int l=1;
    while(l<=n)l<<=1;
    solve(0,l);
    for(int i=0;i<n;i++)printf("%d ",f[i]);
    return 0;
}

以上是关于分治FFT的主要内容,如果未能解决你的问题,请参考以下文章

学习笔记分治FFT

[BZOJ4555][TJOI2016&HEOI2016]求和(分治FFT)

分治FFT

分治FFT

分治FFT

模板分治 FFT