FFT高精度乘法

2 篇文章 0 订阅

裸FFT走一波~~~

#include <cmath>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const double PI=acos(-1.0);
char s1[100005];
char s2[100005];
int ans[200005];
struct Complex
{
	double real,ima;
	Complex(double r=0.0,double i=0.0): real(r),ima(i){}
	Complex operator + (Complex &b)const
	{
		return Complex(real+b.real,ima+b.ima);
	}
	Complex operator - (Complex &b)const
	{
		return Complex(real-b.real,ima-b.ima);
	}
	Complex operator * (Complex &b)const
	{
		return Complex(real*b.real-ima*b.ima,real*b.ima+ima*b.real);
	}
};
Complex a[200005];
Complex b[200005];
Complex c[200005];
void rader(Complex* a,int len)
{
	int j=len>>1;
	for(int i=1;i<len-1;i++)
	{
		if(i<j)swap(a[i],a[j]);
		int k=len>>1;
		while(j>=k)
		{
			j-=k;
			k>>=1;
		}
		if(j<k)j+=k;
	}
}
void fft(Complex* a,int len,int on)
{
	rader(a,len);
	for(int ll=2;ll<=len;ll*=2)
	{
		double ang=on*2*PI/ll;
		Complex wn(cos(ang),sin(ang));
		for(int i=0;i<len;i+=ll)
		{
			Complex w(1.0,0.0);
			for(int j=i;j<i+ll/2;j++)
			{
				Complex u=a[j];
				Complex t=w*a[j+ll/2];
				a[j]=u+t;
				a[j+ll/2]=u-t;
				w=w*wn;
			}
		}
	}
	if(on==-1)
	{
		for(int i=0;i<len;i++)
		a[i].real/=len;
	}
}
int main()
{
	scanf("%s%s",s1,s2);
	int lena=strlen(s1);
	int lenb=strlen(s2);
	int len=1;
	while(len<2*lena||len<2*lenb)len*=2;
	int o=0;
	for(o=0;o<lena;o++)
	{
	a[o].real=s1[lena-o-1]-'0';
	a[o].ima=0.0;	
	}
	while(o<len)
	{
	a[o].real=0;	
	a[o].ima=0;	
	o++;
	}
	for(o=0;o<lenb;o++)
	{
	b[o].real=s2[lenb-o-1]-'0';
	b[o].ima=0.0;	
	}
	while(o<len)
	{
	b[o].real=0;	
	b[o].ima=0;
	o++;
	}
	fft(a,len,1);
	fft(b,len,1);
	for(int i=0;i<len;i++)
	c[i]=a[i]*b[i];
	fft(c,len,-1);
	for(int i=0;i<len;i++)
	ans[i]=int(c[i].real+0.5);
	for(int i=0;i<len;i++)
	{
		ans[i+1]+=ans[i]/10;
		ans[i]%=10;
	}
	int high;
	for(int i=len-1;i>=0;i--)
	{
		if(ans[i])
		{
			high=i;
			break;
		}
	}
	for(int i=high;i>=0;i--)
	printf("%d",ans[i]);
	return 0;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值