码迷,mamicode.com
首页 > 其他好文 > 详细

分治FFT

时间:2020-01-01 18:54:42      阅读:39      评论:0      收藏:0      [点我收藏+]

标签:不能   形式   ret   c++   getc   int   namespace   turn   its   

一、处理的问题

给出多项式\(g[0...n]\),求出\(f[0...n]\)满足\(f_i=\sum\limits_{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+=\sum\limits_{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

标签:不能   形式   ret   c++   getc   int   namespace   turn   its   

原文地址:https://www.cnblogs.com/nofind/p/12129300.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!