神秘分治FFT求调
查看原帖
神秘分治FFT求调
1125685
Frielen楼主2024/11/19 12:37
#include<cstdio>
#include<cmath>
#include<algorithm>
using std::swap;
#define ldb long double
#define int long long
const int N=4e5+9,limit=32000;
const ldb pi=acos(-1.0);
struct comp{
    ldb x,y;
    comp (ldb xx=0,ldb yy=0){x=xx,y=yy;}
}a1[N],a2[N],b[N];
int p=998244353;
int l,r[N];
comp operator + (comp a,comp b){return comp(a.x+b.x,a.y+b.y);}
comp operator - (comp a,comp b){return comp(a.x-b.x,a.y-b.y);}
comp operator * (comp a,comp b){return comp(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
int n,m,kk;
void FFT(int lim,comp *s,int typ){
	for(int i=0;i<lim;i++) if(i<r[i]) swap(s[i],s[r[i]]);
	for(int mid=1;mid<lim;mid<<=1){
		comp Wnk(cosl(pi/mid),typ*sinl(pi/mid));
		for(int ri=mid<<1,j=0;j<lim;j+=ri){
            comp w(1,0);
            for(int k=0;k<mid;k++,w=w*Wnk){
                comp x=s[j+k],y=w*s[j+mid+k];
                s[j+k]=x+y;
                s[j+mid+k]=x-y;
            }
        }
	}
}
void NTT(int *x,int *y,int len,int *ans){
	int lim=1;
	comp X1[N],X2[N],Y[N];
	for(int i=0;i<n;i++){
		X1[i]={(x[i]/limit),(x[i]%limit)};
		X2[i]={(x[i]/limit),(-x[i]%limit)};
	}
	for(int i=0;i<n;i++) Y[i]={(y[i]/limit),(y[i]%limit)};
	while(lim<=len) lim<<=1,l++;
	for(int i=0;i<=lim;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
	FFT(lim,X1,1);
	FFT(lim,X2,1);
	FFT(lim,Y,1);
	for(int i=0;i<=lim;i++) Y[i].x/=lim,Y[i].y/=lim;
  	for(int i=0;i<=lim;i++) X1[i]=X1[i]*Y[i];
  	for(int i=0;i<=lim;i++) X2[i]=X2[i]*Y[i];
  	FFT(lim,X1,-1);
  	FFT(lim,X2,-1);
  	for(int i=0;i<len;i++){
    	int A1,A2,A3,A4;
    	A1=(int)floor((X1[i].x+X2[i].x)/2+0.49)%p;
    	A2=(int)floor((X1[i].y+X2[i].y)/2+0.49)%p;
    	A3=((int)floor(X1[i].y+0.49)-A2)%p;
    	A4=((int)floor(X2[i].x+0.49)-A1)%p;
    	ans[i]=((A1*limit+(A2+A3))%p*limit%p+A4)%p;
    	ans[i]=(ans[i]+p)%p;
  	}
}
int qpow(int a,int q){
	int res=1;
	while(q){
		if(q&1) res=(res*q)%p;
		a=(a*a)%p;
		q>>=1;
	}
	return res;
}
int A1[N],c[N],d[N],ans[N],cnt;
void NTT_inverse(int len,int *a,int *b){
	if(len==1){b[0]=qpow(a[0],p-2);return;}
	NTT_inverse(len+1>>1,a,b);
	for(int i=1;i<=len;i++) printf("%lld ",b[i]);
	NTT(a,b,len,c);
	NTT(c,b,len,d);
	for(int i=0;i<len;i++) b[i]=(b[i]+b[i])%p;
	for(int i=0;i<len;i++) b[i]=(b[i]+p-d[i])%p;
}
signed main(){
	scanf("%lld",&n);
	for(int i=0;i<n;i++) scanf("%lld",&A1[i]);
	int now=1;
	while(now<n) now<<=1;
	NTT_inverse(now,A1,ans);
	for(int i=0;i<n;i++) printf("%lld ",ans[i]);
	return 0;
}
2024/11/19 12:37
加载中...