[AHOI2001]多项式乘法,洛谷P2553,字符串+FFT?

本文深入探讨了字符串处理与多项式乘法在算法竞赛中的应用,重点介绍了离散傅立叶变换(DFT)算法在解决此类问题中的关键作用。通过具体实例,展示了如何使用C++实现DFT算法进行多项式乘法运算,同时提供了详细的代码解释,为读者理解复杂数学概念和算法提供了清晰的路径。

正题

       这题就是烦吧。

       关键是字符串的处理,然后两个做一次多项式乘法就输出?

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;

struct complex{
	double x,y;
	complex operator+(const complex a)const {return (complex){x+a.x,y+a.y};}
	complex operator-(const complex a)const {return (complex){x-a.x,y-a.y};}
	complex operator*(const complex a)const {return (complex){x*a.x-y*a.y,x*a.y+y*a.x};}
}a[30010],b[30010];
char s[1000010];
double co[30010],si[30010];
int where[30010];
int n,m,lim,l;
int t=0,temp,wr;
const double Pi=acos(-1.0)*2.0;

void dft(complex *now,int idft){
	for(int i=0;i<lim;i++) if(where[i]>i) swap(now[i],now[where[i]]);
	complex wn,w,a,b;
	for(int l=2;l<=lim;l*=2){
		wn=(complex){co[l],idft*si[l]};
		for(int i=0;i<lim;i+=l){
			w=(complex){1,0};
			for(int x=i,y=i+l/2;y<i+l;x++,y++,w=w*wn){
				a=now[x],b=w*now[y];
				now[x]=a+b;
				now[y]=a-b;
			}
		}
	}
}

void fill_in(complex *now,int&mmax){
	while(s[t]!=')'){
		if(s[t]=='+') {t++;continue;}
		if(s[t]>='0' && s[t]<='9'){
			temp=s[t]-'0';
			if(s[t+1]>='0' && s[t+1]<='9') t++,temp=temp*10+s[t]-'0';
			if(s[t+1]=='+' || s[t+1]==')') wr=0;
			else{
				t+=3;
				wr=s[t]-'0';
				if(s[t+1]>='0' && s[t+1]<='9') t++,wr=wr*10+s[t]-'0';
			}
			now[wr].x=temp;
			mmax=max(wr+1,mmax);
		}
		t++;
	}
}

int main(){
	for(int i=2;i<=30000;i*=2) co[i]=cos(Pi/i),si[i]=sin(Pi/i);
	while(scanf("%s",s)!=EOF){
		for(int i=0;i<=30000;i++) a[i].x=a[i].y=b[i].x=b[i].y=0;
		n=m=0;
		t=1,temp=0;
		fill_in(a,n);t+=3;fill_in(b,m);
		lim=1,l=0;
		while(lim<n+m-1) lim*=2,l++;
		for(int i=0;i<lim;i++) where[i]=((where[i>>1]>>1)|((i&1)<<(l-1)));
		dft(a,1);dft(b,1);
		for(int i=0;i<lim;i++) a[i]=a[i]*b[i];
		dft(a,-1);
		if(n+m-2>=1)printf("%da^%d",(int)(a[n+m-2].x/lim+0.5),n+m-2);
		for(int i=n+m-3;i>=1;i--) printf("+%da^%d",(int)(a[i].x/lim+0.5),i);
		if(n+m-2==0) printf("%d\n",(int)(a[0].x/lim+0.5));
		else printf("+%d\n",(int)(a[0].x/lim+0.5));
	}
}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值