解题:洛谷4721 [模板]分治FFT

时间:2023-03-09 00:25:12
解题:洛谷4721 [模板]分治FFT

题面

这是CDQ入门题,不要被题目名骗了,这核心根本不在不在FFT上啊=。=

因为后面的项的计算依赖于前面的项,不能直接FFT。所以用CDQ的思想,算出前面然后考虑给后面的贡献

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=,mod=;
int a[*N],b[*N],rev[*N],f[N],g[N],n,G,Gi;
void exGCD(int a,int b,int &x,int &y)
{
if(!b) {x=,y=; return ;}
exGCD(b,a%b,y,x),y-=a/b*x;
}
int Qpow(int x,int k)
{
if(k==) return x;
int tmp=Qpow(x,k/);
return k%?1ll*tmp*tmp%mod*x%mod:1ll*tmp*tmp%mod;
}
int Inv(int x,int m)
{
int xx,yy;
exGCD(x,m,xx,yy);
return (xx%m+m)%m;
}
void NTT(int *arr,int len,int typ)
{
for(int i=;i<=len;i++)
if(rev[i]>i) swap(arr[rev[i]],arr[i]);
for(int i=;i<=len;i<<=)
{
int lth=i>>,ort=Qpow(~typ?G:Gi,(mod-)/i);
for(int j=;j<len;j+=i)
{
int ori=,tmp;
for(int k=j;k<j+lth;k++,ori=1ll*ori*ort%mod)
{
tmp=1ll*ori*arr[k+lth]%mod;
arr[k+lth]=(arr[k]-tmp+mod)%mod;
arr[k]=(arr[k]+tmp)%mod;
}
}
}
if(typ==-)
for(int i=,ni=Inv(len,mod);i<len;i++)
arr[i]=1ll*arr[i]*ni%mod;
}
void CDQ(int l,int r,int mid)
{
int len=r-l+,m=;
for(int i=l;i<=mid;i++) a[i-l]=f[i];
for(int i=;i<len;i++) b[i]=g[i]; len+=mid-l+;
while(m<=len) m<<=;
for(int i=;i<=m;i++) rev[i]=(rev[i>>]>>)+(i&)*(m>>);
NTT(a,m,),NTT(b,m,);
for(int i=;i<=m;i++) a[i]=1ll*a[i]*b[i]%mod;
NTT(a,m,-);
for(int i=mid+;i<=r;i++) f[i]+=a[i-l],f[i]%=mod;
for(int i=;i<=m;i++) a[i]=b[i]=;
}
void Divide(int l,int r)
{
if(l==r) return;
int mid=(l+r)/;
Divide(l,mid),CDQ(l,r,mid),Divide(mid+,r);
}
int main()
{
scanf("%d",&n);
for(int i=;i<n;i++) scanf("%d",&g[i]);
f[]=,G=,Gi=Inv(G,mod),Divide(,n-);
for(int i=;i<n;i++) printf("%d ",f[i]);
return ;
}