HDU1402 A * B Problem Plus(FFT)

http://acm.hdu.edu.cn/showproblem.php?pid=1402

初学FFT。

http://www.cnblogs.com/WABoss/p/FFT_Note.html

直接上代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define MAXN 133333
const double PI=acos(-1.0);

struct Complex{
	double real,imag;
	Complex(){}
	Complex(double _real,double _imag):real(_real),imag(_imag){}
	Complex operator-(const Complex &cp) const{
		return Complex(this->real-cp.real,this->imag-cp.imag);
	}
	Complex operator+(const Complex &cp) const{
		return Complex(this->real+cp.real,this->imag+cp.imag);
	}
	Complex operator*(const Complex &cp) const{
		return Complex(this->real*cp.real-this->imag*cp.imag,this->real*cp.imag+this->imag*cp.real);
	}
	void setValue(double _real=0,double _imag=0){
		real=_real; imag=_imag;
	}
};

int len;
Complex wn[MAXN],wn_anti[MAXN];

void FFT(Complex y[],int op){
	// Rader, 位逆序置换 
	for(int i=1,j=len>>1,k; i<len-1; ++i){
		if(i<j) swap(y[i],y[j]);
		k=len>>1;
		while(j>=k){
			j-=k;
			k>>=1;
		}
		if(j<k) j+=k;
	}
	// h=1,Wn^0=1 
	for(int h=2; h<=len; h<<=1){
		// Wn = e^(2*PI*i/n),如果是插值Wn = e^(-2*PI*i/n),i虚数单位 
		Complex Wn = (op==1 ? wn[h] : wn_anti[h]);
		for(int i=0; i<len; i+=h){
			Complex W(1,0);
			for(int j=i; j<i+(h>>1); ++j){
				Complex u=y[j],t=W*y[j+(h>>1)];
				y[j]=u+t;
				y[j+(h>>1)]=u-t;
				W=W*Wn;
			}
		}
	}
	if(op==-1){
		for(int i=0; i<len; ++i) y[i].real/=len;
	}
}
void Convolution(Complex A[],Complex B[],int n){
	// 初始化 
	for(len=1; len<(n<<1); len<<=1);
	for(int i=n; i<len; ++i){
		A[i].setValue();
		B[i].setValue();
	}
	// e^(θi) = cosθ+isinθ -> Wn = cos(2*PI/n)+isin(2*PI/n)
	for(int i=0; i<=len; ++i){ // 预处理 
		wn[i].setValue(cos(2.0*PI/i),sin(2.0*PI/i)); 
		wn_anti[i].setValue(wn[i].real,-wn[i].imag);
	}
	FFT(A,1); FFT(B,1);
	for(int i=0; i<len; ++i){
		A[i]=A[i]*B[i];
	}
	FFT(A,-1);
}

char s1[55555],s2[55555];
Complex A[MAXN],B[MAXN];
int ans[MAXN];

int main(){
	while(scanf("%s%s",s1,s2)==2){
		int l1=strlen(s1),l2=strlen(s2);
		for(int i=0; i<l1; ++i){
			A[i].setValue(s1[l1-i-1]-'0');
		}
		for(int i=0; i<l2; ++i){
			B[i].setValue(s2[l2-i-1]-'0');
		}
		if(l1<l2){
			for(int i=l1; i<l2; ++i) A[i].setValue();
			l1=l2;
		}else{
			for(int i=l2; i<l1; ++i) B[i].setValue();
		}
		Convolution(A,B,l1);
		for(int i=0; i<len; ++i){
			ans[i]=(int)(A[i].real+0.5);
		}
		for(int i=0; i<len; ++i){
			ans[i+1]+=ans[i]/10;
			ans[i]%=10;
		}
		while(--len && ans[len]==0);
		for(int i=len; i>=0; --i) printf("%d",ans[i]);
		putchar('\n');
	}
	return 0;
}

 

posted @ 2016-08-31 15:47  WABoss  阅读(310)  评论(0编辑  收藏  举报