Problem Description
Calculate A * B.
Input
Each line will contain two integers A and B. Process to end of file.
Note: the length of each integer will not exceed 50000.
Output
For each case, output A * B in one line.
Sample Input
1
2
1000
2
Sample Output
2
2000
Solution
五万位的高精乘,直接乘显然会爆!
这时就用上了“高大上”的FFT( 快速傅里叶变换),用以计算卷积的 O(N log N) 算法。
把原数看成是 x=10 的多项式,就能直接上法法塔了。
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=5e4+5;
const double Pi=acos(-1.0);
struct complex
{
double r,i;
complex(){}
complex(double x,double y){r=x,i=y;}
complex operator +(const complex &x)const
{
return complex(r+x.r,i+x.i);
}
complex operator -(const complex &x)const
{
return complex(r-x.r,i-x.i);
}
complex operator *(const complex &x)const
{
return complex(r*x.r-i*x.i,i*x.r+r*x.i);
}
}f1[N<<2],f2[N<<2];
int ans[N<<2];
char s1[N],s2[N];
inline void FFT(complex *y,int n,int rev)
{
for(int i=1;i<n;i++)
{
int j=0;
for(int k=n>>1,t=i;k;k>>=1,t>>=1) j=j<<1|t&1;
if(i<j) swap(y[i],y[j]);
}
for(int s=2;s<=n;s<<=1)
{
complex wn(cos(rev*2*Pi/s),sin(rev*2*Pi/s));
for(int j=0;j<n;j+=s)
{
complex w(1,0);
for(int k=j;k<j+s/2;k++)
{
complex x=w*y[k+s/2];
y[k+s/2]=y[k]-x;
y[k]=y[k]+x;
w=w*wn;
}
}
}
if(rev==-1) for(int i=0;i<n;i++) y[i].r/=n;
}
int main()
{
while(~scanf("%s%s",&s1,&s2))
{
int len1=strlen(s1),len2=strlen(s2),len=1;
while(len<len1+len2) len<<=1;
for(int i=0;i<len1;i++) f1[i]=complex(s1[len1-i-1]-'0',0);
for(int i=len1;i<len;i++) f1[i]=complex(0,0);
for(int i=0;i<len2;i++) f2[i]=complex(s2[len2-i-1]-'0',0);
for(int i=len2;i<len;i++) f2[i]=complex(0,0);
FFT(f1,len,1),FFT(f2,len,1);
for(int i=0;i<len;i++) f1[i]=f1[i]*f2[i];
FFT(f1,len,-1);
for(int i=0;i<len;i++) ans[i]=int(f1[i].r+0.5);
for(int i=0;i<len;i++) ans[i+1]+=ans[i]/10,ans[i]%=10;
while(len>1 && !ans[len-1]) len--;
for(int i=len-1;i>=0;i--) putchar(ans[i]+'0');
putchar('\n');
}
return 0;
}