社区讨论

拆系数FFT求助(精度问题)

P4245【模板】任意模数多项式乘法参与者 2已保存回复 1

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
1 条
当前快照
1 份
快照标识符
@mkf79y0p
此快照首次捕获于
2026/01/15 16:41
上个月
此快照最后确认于
2026/01/18 10:35
上个月
查看原帖
本人在突破50pts大关后屡次90,95分,虽然有longdouble的加持但仍旧先后WA了:15&17,16,11,12(修改了拆的系数),但同为5次FFT,为什么我的代码困于精度问题而非时间,求高人提升精度🙏(或找出原因
CPP
#include <bits/stdc++.h>
using namespace std;
struct Cp{
	long double a,b;
	Cp(long double x,long double y):a(x),b(y){}
	Cp(){}
	Cp operator+(Cp x){return(Cp){x.a+a,x.b+b};}
	Cp operator-(Cp x){return(Cp){a-x.a,b-x.b};}
	Cp operator*(Cp x){return(Cp){a*x.a-b*x.b,a*x.b+b*x.a};}
};
const int P=65000,N=3e5+10;
int r[N],lim,l,n,m,p;
int a[N],b[N];
const long double pi=3.1415926535897932384626;
void fft(Cp*A,int type){
	for(int i=0;i<lim;i++){
		if(i<r[i])swap(A[i],A[r[i]]);
	}
	for(int mid=1;mid<lim;mid<<=1){
		Cp Wn(cos(pi/mid),type*sin(pi/mid));
		for(int j=0,R=mid<<1;j<lim;j+=R){
			Cp w(1,0);
			for(int k=0;k<mid;k++,w=w*Wn){
				Cp x=A[j+k],y=w*A[j+k+mid];
				A[j+k]=x+y;
				A[j+k+mid]=x-y;
			}
		}
	}
}
Cp a1[N],a2[N];
int ans[N];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n>>m>>p;
	for(lim=1;lim<=n+m;++l,lim<<=1);
	for(int i=0;i<lim;i++)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
	for(int i=0;i<=n;i++)cin>>a[i],a[i]%=p;
	for(int i=0;i<=m;i++)cin>>b[i],b[i]%=p;
	for(int i=0;i<lim;i++)a1[i].a=a[i]%P,a1[i].b=a[i]/P;
	for(int i=0;i<lim;i++)a2[i].a=b[i]%P,a2[i].b=b[i]/P;
	fft(a1,1),fft(a2,1);
	for(int i=0;i<lim;i++)a1[i]=a1[i]*a2[i];
	fft(a1,-1);
	for(int i=0;i<lim;i++)a2[i].a=a[i]/P,a2[i].b=b[i]/P;
	fft(a2,1);
	for(int i=0;i<lim;i++)a2[i]=a2[i]*a2[i];
	fft(a2,-1);
	long long tmp=(1ll*P*P+1)%p;
	for(int i=0;i<lim;i++){
		ans[i]=((long long)(a1[i].b/lim+0.5))%p*P%p;
	}
	for(int i=0;i<lim;i++){
		ans[i]+=(((long long)(a1[i].a/lim+0.5)%p)+tmp*((long long)(a2[i].b/lim/2+0.5)%p))%p;
		ans[i]%=p;
	}
	for(int i=0;i<=n+m;i++){
		cout<<ans[i]<<' ';
	}
	return 0;
}

回复

1 条回复,欢迎继续交流。

正在加载回复...