1. 程式人生 > >高精度乘法 普通(n^2)+fft(nlogn)

高精度乘法 普通(n^2)+fft(nlogn)

高精度乘法核心為

ci=j=1iajbij+1

普通演算法時間複雜度為O(n2).
又由於是卷積形式,可用fft優化為O(nlogn)

普通版

#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; }