给出两个n位10进制整数x和y,你需要计算x*y。
输入格式:
第一行一个正整数n。 第二行描述一个位数为n的正整数x。 第三行描述一个位数为n的正整数y。
输出格式:
输出一行,即x*y的结果。(注意判断前导0)
数据范围:
n<=60000
来源:bzoj2179
本题数据为洛谷自造数据,使用CYaRon耗时5分钟完成数据制作。
分析:
之前都是拿python水过这题的。今天学懂了FFT,特地来刷一波。
思路没什么讲的,就是FFT,不过注意前导零,还要注意有的位数上会大于10,需要处理。
Code:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 #include<iostream> 7 #include<iomanip> 8 using namespace std; 9 const double pi=acos(-1.0); 10 const int N=5e5+7; 11 int n,m,L,c[N],r[N]; 12 char ca[N],cb[N]; 13 struct complex{ 14 double x;double y; 15 complex(double xx=0,double yy=0){x=xx;y=yy;} 16 }w1[N],w2[N]; 17 complex operator + (complex a,complex b){return complex(a.x+b.x,a.y+b.y);} 18 complex operator - (complex a,complex b){return complex(a.x-b.x,a.y-b.y);} 19 complex operator * (complex a,complex b){return complex(a.x*b.x-a.y*b.y,a.x*b.y+b.x*a.y);} 20 void FFT(complex *A,int flag) 21 { 22 for(int i=0;i<n;i++) 23 if(i<r[i])swap(A[i],A[r[i]]); 24 for(int i=1;i<n;i<<=1){ 25 complex wn(cos(pi/i),flag*sin(pi/i)); 26 for(int j=0;j<n;j+=(i<<1)){ 27 complex w(1,0); 28 for(int k=0;k<i;k++,w=w*wn){ 29 complex a=A[j+k],b=w*A[i+j+k]; 30 A[j+k]=a+b,A[i+j+k]=a-b;} 31 } 32 } 33 } 34 int main() 35 { 36 scanf("%d",&n);n--;m=2*n; 37 scanf("%s",ca); 38 for(int i=0;i<=n;i++)w1[i].x=ca[n-i]-‘0‘; 39 scanf("%s",cb); 40 for(int i=0;i<=n;i++)w2[i].x=cb[n-i]-‘0‘; 41 for(n=1;n<=m;n<<=1)++L; 42 for(int i=0;i<n;i++) 43 r[i]=((r[i>>1]>>1)|((i&1)<<(L-1))); 44 FFT(w1,1);FFT(w2,1); 45 for(int i=0;i<=n;i++)w1[i]=w1[i]*w2[i]; 46 FFT(w1,-1); 47 for(int i=0;i<=m;i++)c[i]=(int)(w1[i].x/n+0.5); 48 for(int i=0;i<=m;i++) 49 if(c[i]>=10){ 50 c[i+1]+=c[i]/10;c[i]%=10; 51 if(i==m)m++;} 52 while(m>0&&c[m]==0)m--; 53 for(int i=m;i>=0;i--)printf("%d",c[i]); 54 return 0; 55 }
洛谷P1919 A*B problem 快速傅里叶变换模板 [FFT]
原文:https://www.cnblogs.com/cytus/p/9215645.html