1. 程式人生 > >洛谷P1919 【模板】A*B Problem升級版(FFT)

洛谷P1919 【模板】A*B Problem升級版(FFT)

targe 空間 break 這就是 bre color show print lex

傳送門

話說FFT該不會真的只能用來做這種板子吧……

我們把兩個數字的每一位都看作多項式的系數

然後這就是一個多項式乘法

上FFT就好了

然後去掉前導零

(然而連FFT的板子都背不來orz,而且空間又開小了……)

 1 //minamoto
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cmath>
 5 using namespace std;
 6 char sr[1<<21],z[20];int C=-1
,Z; 7 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;} 8 inline void print(int x){ 9 if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x; 10 while(z[++Z]=x%10+48,x/=10); 11 while(sr[++C]=z[Z],--Z); 12 } 13 const int N=2e5+5;const double Pi=acos(-1.0); 14 int r[N],l=0,limit=1,c[N],n;char
sa[N],sb[N]; 15 struct complex{ 16 double x,y; 17 complex(double xx=0,double yy=0){x=xx,y=yy;} 18 inline complex operator +(complex b){return complex(x+b.x,y+b.y);} 19 inline complex operator -(complex b){return complex(x-b.x,y-b.y);} 20 inline complex operator *(complex b){return
complex(x*b.x-y*b.y,x*b.y+y*b.x);} 21 }a[N],b[N]; 22 void FFT(complex *a,int type){ 23 for(int i=0;i<limit;++i) 24 if(i<r[i]) swap(a[i],a[r[i]]); 25 for(int mid=1;mid<limit;mid<<=1){ 26 complex Wn(cos(Pi/mid),type*sin(Pi/mid)); 27 for(int R=mid<<1,j=0;j<limit;j+=R){ 28 complex w(1,0); 29 for(int k=0;k<mid;++k,w=w*Wn){ 30 complex x=a[j+k],y=w*a[j+k+mid]; 31 a[j+k]=x+y,a[j+k+mid]=x-y; 32 } 33 } 34 } 35 } 36 int main(){ 37 // freopen("testdata.in","r",stdin); 38 scanf("%d",&n),--n; 39 scanf("%s%s",sa,sb); 40 for(int i=0;i<=n;++i) a[i].x=sa[n-i]-0,b[i].x=sb[n-i]-0; 41 while(limit<=n*2) limit<<=1,++l; 42 for(int i=0;i<=limit;++i) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1)); 43 FFT(a,1),FFT(b,1); 44 for(int i=0;i<=limit;++i) a[i]=a[i]*b[i]; 45 FFT(a,-1); 46 for(int i=0;i<=limit;++i) c[i]=(int)(a[i].x/limit+0.5); 47 for(int i=0;i<=limit;++i) 48 if(c[i]>9){ 49 c[i+1]+=c[i]/10,c[i]%=10; 50 if(i+1>limit) ++limit; 51 } 52 for(int i=limit;i>=0;--i) 53 if(c[i]==0) --limit; 54 else break; 55 for(int i=limit;i>=0;--i) print(c[i]); 56 Ot(); 57 return 0; 58 }

洛谷P1919 【模板】A*B Problem升級版(FFT)