【模版】FFT / NTT
FFT
typedef complex<double> cp;
void init(int k)
{
int len=1<<k;
for(int i=0;i<len;i++)
rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
}
void fft(cp *a,int n,int flag)
{
for(int i=0;i<n;i++)
if(i<rev[i])
swap(a[i],a[rev[i]]);
for(int h=1;h<n;h*=2)
{
cp wn=exp(cp(0,flag*PI/h));
for(int j=0;j<n;j+=h*2)
{
cp w(1,0);
for(int k=j;k<j+h;k++)
{
cp x=a[k];
cp y=w*a[k+h];
a[k]=x+y;
a[k+h]=x-y;
w*=wn;
}
}
}
if(flag==-1)
for(int i=0;i<n;i++)
a[i]/=n;
}
NTT是FFT的数论版本,其适用于模意义下的整数域。
然而,另一种情况,当值域达不到模数时,也可认为是全体整数域。此时其不会丢失精度,显著优于FFT,如前几天的牛客第八场J题。
NTT较FFT的改动非常少。此外998244353的一个原根是3,在赛场上知道这个可以直接用,这是非常好的。
const int i3=inv(3);
void init(int k)
{
int len=1<<k;
for(int i=0;i<len;i++)
rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
return;
}
void fft(int *a,int n,int flag)
{
for(int i=0;i<n;i++)
if(i<rev[i])
swap(a[i],a[rev[i]]);
for(int h=1;h<n;h*=2)
{
int wn=pow_mod(flag==1?3:i3,(mod-1)/(h<<1),mod);
for(int j=0;j<n;j+=h*2)
{
int w=1;
for(int k=j;k<j+h;k++)
{
int x=a[k];
int y=w*a[k+h]%mod;
a[k]=(x+y)%mod;
a[k+h]=(x-y+mod)%mod;
w=w*wn%mod;
}
}
}
if(flag==-1)
{
int INV=inv(n);
for(int i=0;i<n;i++)
a[i]=a[i]*INV%mod;
}
return;
}

浙公网安备 33010602011771号