【模版】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;
}
posted @ 2025-08-10 22:38  Astral_Plane  阅读(9)  评论(0)    收藏  举报