题目链接
题意:计算高精度的A*B
FFT 来搞一下,学习的链接
1)http://www.gatevin.moe/acm/fft%E7%AE%97%E6%B3%95%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/
2)http://www.cnblogs.com/kuangbin/p/3210389.html
使用了kuangbin的模板,结合Gatevin的讲解,很好的理解
A*B正好是符合多项式乘法的规律,我们直接乘,然后计算出新的系数就是了,但是要注意系数是可能大于10的,所以要处理进位,倒着做就好了
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define cl(a,b) memset(a,b,sizeof(a))
#define ll long long
#define pb push_back
#define gcd __gcd
const double EPS = 1e-8;
const int maxn = 1e5+1000;
const int inf = 0x3f3f3f3f;
const double PI = acos(-1.0);
struct complex{
double r,i;
complex(double _r=0.0,double _i=0.0){
r=_r;i=_i;
}
complex operator+(const complex&b){
return complex(r+b.r,i+b.i);
}
complex operator-(const complex&b){
return complex(r-b.r,i-b.i);
}
complex operator*(const complex&b){
return complex(r*b.r-i*b.i,r*b.i+i*b.r);
}
};
/*
进行FFT和IFFT前的反转变换
位置i 和 i的二进制反转表示的数 位置交换
比如 1<->4:001 <-> 100
len 必须是2的幂
*/
void change(complex y[],int len){
int i,j,k;
for(i=1,j=len/2;i<len-1;i++){
if(i<j)swap(y[i],y[j]);//交换下标互为反转的元素,i<j保证只交换一次
k=len/2;//i做正常的加1,j做反转的加一,始终保持i,j是反转的
while(j>=k){
j-=k;k/=2;
}
if(j<k)j+=k;
}
}
/*
做FFT len必须是2的幂
on==1是DFT,on==-1是IDFT
*/
void fft(complex y[],int len,int on){
change(y,len);
for(int h=2;h<=len;h<<=1){
complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
for(int j=0;j<len;j+=h){
complex w(1,0);
for(int k=j;k<j+h/2;k++){
complex u=y[k];
complex t=w*y[k+h/2];
y[k]=u+t;
y[k+h/2]=u-t;
w=w*wn;
}
}
}
if(on==-1)for(int i=0;i<len;i++)y[i].r/=len;
}
char str[maxn],str2[maxn];
complex a[maxn<<1],b[maxn<<1];
int sum[maxn<<1];
int main(){
while(~scanf("%s%s",str,str2)){
int len1=strlen(str);
int len2=strlen(str2);
int len=1;
while(len<len1*2 || len<len2*2)len<<=1;
for(int i=0;i<len1;i++)a[i]=complex(str[len1-1-i]-'0',0);
for(int i=len1;i<len;i++)a[i]=complex(0,0);
for(int i=0;i<len2;i++)b[i]=complex(str2[len2-1-i]-'0',0);
for(int i=len2;i<len;i++)b[i]=complex(0,0);
fft(a,len,1);
fft(b,len,1);
for(int i=0;i<len;i++)
a[i]=a[i]*b[i];
fft(a,len,-1);
//一般是需要处理精度误差
for(int i=0;i<len;i++)sum[i]=(int)(a[i].r+0.5);
for(int i=0;i<len;i++){
sum[i+1]+=sum[i]/10;
sum[i]%=10;
}
len = len1+len2-1;
while(sum[len]<=0 && len > 0)len--;
for(int i=len;i>=0;i--)printf("%c",sum[i]+'0');
printf("\n");
}
return 0;
}