高精度乘法 普通(n^2)+fft(nlogn)
阿新 • • 發佈:2019-02-20
高精度乘法核心為
ci=∑j=1iaj⋅bi−j+1
普通演算法時間複雜度為
又由於是卷積形式,可用fft優化為
普通版
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=405;
int n,m,a[N],b[N],c[N];
char s[N];
int main()
{
//freopen("lx.in","r",stdin);
scanf("%s",s+1);
n=strlen(s+1);
reverse(s+1,s+n+1);
for(int i=1;i<=n;i++)a[i]=s[i]-'0';
scanf("%s",s+1);
m=strlen(s+1);
reverse(s+1,s+m+1);
for(int i=1;i<=m;i++)b[i]=s[i]-'0';
for(int i=1;i<=m+n;i++)
for(int j=1;j<=n&&i-j+1>0;j++)
c[i]+=a[j]*b[i-j+1 ];
for(int i=1;i<=m+n;i++)
c[i+1]+=c[i]/10,c[i]%=10;
int len=m+n;
while(!c[len])len--;
for(int i=len;i>=1;i--)
cout<<c[i];
return 0;
}
FFT版
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<complex>
using namespace std;
const int N=513;
const double PI=acos(-1);
int n,m,pos[N],ans[N];
char s[N];
complex<double>f1[N],f2[N];
void rev(int k)
{
for(int i=1;i<k;i++)
pos[i]=(i&1)?(pos[i>>1]>>1)^(k>>1):pos[i>>1]>>1;
}
void fft(complex<double>f[],int len,int on)
{
for(int i=0;i<len;i++)if(i<pos[i])swap(f[i],f[pos[i]]);
for(int i=1;i<len;i<<=1)
{
complex<double>wn(cos(on*PI/i),sin(on*PI/i));
for(int j=0;j<len;j+=(i<<1))
{
complex<double>wi(1,0);
for(int k=j;k<j+i;k++)
{
complex<double>u=f[k],v=f[k+i]*wi;
f[k]=u+v;
f[k+i]=u-v;
wi*=wn;
}
}
}
if(on==-1)
{
for(int i=0;i<len;i++)
f[i]/=len;
}
}
void multi(complex<double>f1[],complex<double>f2[])
{
int len=1;
while(len<m+n)len<<=1;
rev(len);
fft(f1,len,1),fft(f2,len,1);
for(int i=0;i<len;i++)f1[i]*=f2[i];
fft(f1,len,-1);
for(int i=0;i<len;i++)
ans[i]=int(f1[i].real()+0.5);
for(int i=0;i<len;i++)
if(ans[i]>=10)ans[i+1]+=ans[i]/10,ans[i]%=10;
while(!ans[len])len--;
for(int i=len;i>=0;i--)cout<<ans[i];
}
int main()
{
//freopen("lx.in","r",stdin);
scanf("%s",s);
n=strlen(s);
reverse(s,s+n);
for(int i=0;i<n;i++)f1[i]=s[i]-'0';
scanf("%s",s);
m=strlen(s);
reverse(s,s+m);
for(int i=0;i<m;i++)f2[i]=s[i]-'0';
multi(f1,f2);
return 0;
}