题意:
计算A*B(A,B均不超过5e4位)。
题解:
计算A*B 可以把AB的各项化成多项式来相乘
把这两个多项式相乘起来就能得到A*B的结果了。
用FFT可以快速的求出两多项式相乘的结果,然后就可以得到每一位的的结果。
求得A*B的结果之后,做进位处理。
注意最后要去掉前导零,然后倒着输出。
这是第一次写的FFT的题目,所以代码上面有对模版的一些解释。
#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<vector>
using namespace std;
typedef long long ll;
const double PI=acos(-1.0);
const int N=5e4+5;
const int M=(1<<17)+5;//取大于2*N的2的幂
char A[N],B[N];
int ans[M];
struct Complex
{
double real,image;
Complex(double r=0.0,double i=0.0):real(r),image(i){};
Complex operator + (const Complex &b)
{
return Complex(real+b.real,image+b.image);
}
Complex operator - (const Complex &b)
{
return Complex(real-b.real,image-b.image);
}
Complex operator * (const Complex &b)
{
return Complex(real*b.real-image*b.image,image*b.real+real*b.image);
}
Complex operator / (const Complex &b)
{
double r=(real*b.real+image*b.image)/(b.real*b.real+b.image*b.image);
double i=(image*b.real-real*b.image)/(b.real*b.real+b.image*b.image);
return Complex(r,i);
}
}a[M],b[M];
/*
将当前项跟其二进制的倒序交换
倒序过程中
k的初始值是len/2 即可取的二进制的最高位
只有当j比当前的k要大,代表有进位,所以减去后
最后在j<k的时候,补上进位
*/
void change(Complex x[],int len)
{
//0跟最后二进制全1的都不用处理,所以是len-1
for (int i=1 , j=len/2 ; i<len-1 ; ++i)
{
if (i<j)
swap(x[i],x[j]);
//只有i比j小的时候交换,避免重复交换导致交换无效
int k=len/2;
while (j>=k)
{
j-=k;
k/=2;
}
if (j<k)
j+=k;
}
}
/*
dft=1时是DFT dfs=-1时是逆DFT
len必须是2的幂
*/
void FFT(Complex x[],int len,int dft)
{
change(x,len);
for (int h=2 ; h<=len ; h<<=1)
{
Complex wn(cos(dft*2*PI/h),sin(dft*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=x[k];
Complex t=w*x[k+h/2];
x[k]=u+t;
x[k+h/2]=u-t;
w=w*wn;
}
}
}
if (dft==-1)
{
for (int i=0 ; i<len ; ++i)
{
x[i].real/=len;
x[i].image/=len;
}
}
}
int main()
{
while (~scanf("%s%s",A,B))
{
int lena=strlen(A),lenb=strlen(B);
int len=1;
/*得到最长的2*n*/
while (len<lena*2 || len<lenb*2)
len<<=1;
/*将每一位拆开*/
for (int i=0 ; i<len ; ++i)
{
if (i<lena)
a[i]=Complex(A[lena-1-i]-'0',0);
else
a[i]=Complex(0,0);
if (i<lenb)
b[i]=Complex(B[lenb-1-i]-'0',0);
else
b[i]=Complex(0,0);
}
//DFT
FFT(a,len,1);
FFT(b,len,1);
for (int i=0 ; i<len ; ++i)
a[i]=a[i]*b[i];
//DFT-1
FFT(a,len,-1);
memset(ans,0,sizeof(ans));
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 (!ans[len] && len>0)
len--;
for (int i=len ; i>=0 ; --i)
printf("%d",ans[i]);
printf("\n");
}
return 0;
}