A*B problem
题目描述
给出两个n位10进制整数x和y,你需要计算x*y。
输入输出格式
输入格式:
第一行一个正整数n。 第二行描述一个位数为n的正整数x。 第三行描述一个位数为n的正整数y。
输出格式:
输出一行,即x*y的结果。(注意判断前导0)
输入输出样例
说明
数据范围:
n<=60000
来源:bzoj2179
本题数据为洛谷自造数据,使用CYaRon耗时5分钟完成数据制作。
分析:
之前都是拿python水过这题的。今天学懂了FFT,特地来刷一波。<不会FFT的看这里>
思路没什么讲的,就是FFT,不过注意前导零,还要注意有的位数上会大于10,需要处理。
Code:
// luogu-judger-enable-o2 #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<iostream> #include<iomanip> using namespace std; const double pi=acos(-1.0); const int N=5e5+7; int n,m,L,c[N],r[N]; char ca[N],cb[N]; struct complex{ double x;double y; complex(double xx=0,double yy=0){x=xx;y=yy;} }w1[N],w2[N]; complex operator + (complex a,complex b){return complex(a.x+b.x,a.y+b.y);} complex operator - (complex a,complex b){return complex(a.x-b.x,a.y-b.y);} complex operator * (complex a,complex b){return complex(a.x*b.x-a.y*b.y,a.x*b.y+b.x*a.y);} void FFT(complex *A,int flag) { for(int i=0;i<n;i++) if(i<r[i])swap(A[i],A[r[i]]); for(int i=1;i<n;i<<=1){ complex wn(cos(pi/i),flag*sin(pi/i)); for(int j=0;j<n;j+=(i<<1)){ complex w(1,0); for(int k=0;k<i;k++,w=w*wn){ complex a=A[j+k],b=w*A[i+j+k]; A[j+k]=a+b,A[i+j+k]=a-b;} } } } int main() { scanf("%d",&n);n--;m=2*n; scanf("%s",ca); for(int i=0;i<=n;i++)w1[i].x=ca[n-i]-'0'; scanf("%s",cb); for(int i=0;i<=n;i++)w2[i].x=cb[n-i]-'0'; for(n=1;n<=m;n<<=1)++L; for(int i=0;i<n;i++) r[i]=((r[i>>1]>>1)|((i&1)<<(L-1))); FFT(w1,1);FFT(w2,1); for(int i=0;i<=n;i++)w1[i]=w1[i]*w2[i]; FFT(w1,-1); for(int i=0;i<=m;i++)c[i]=(int)(w1[i].x/n+0.5); for(int i=0;i<=m;i++) if(c[i]>=10){ c[i+1]+=c[i]/10;c[i]%=10; if(i==m)m++;} while(m>0&&c[m]==0)m--; for(int i=m;i>=0;i--)printf("%d",c[i]); return 0; }