【洛谷P1919】【模板】A*B Problem升級版
阿新 • • 發佈:2020-09-15
題目
題目連結:https://www.luogu.com.cn/problem/P1919
給出兩個數 \(a,b\),求 \(a\times b\)。
思路
類比列豎式的時候,從低位往高位數,分別為 \(i,j\) 兩位的數字相乘會到第 \(i+j-1\) 位。
這其實就是一個卷積的形式,直接上 FFT 即可。
注意需要在跑完 FFT 之後進位。
時間複雜度 \(O(n\log n)\)。
程式碼
#include <bits/stdc++.h> #define cp complex<double> using namespace std; const int N=3000010; const double pi=acos(-1); int n,m,Maxn=1,rev[N],h[N]; char ch[N]; cp f[N],g[N]; void fft(cp *f,int tag) { for (int i=0;i<Maxn;i++) if (i<rev[i]) swap(f[i],f[rev[i]]); for (int mid=1;mid<Maxn;mid<<=1) { cp temp(cos(pi/mid),tag*sin(pi/mid)); for (int i=0;i<Maxn;i+=(mid<<1)) { cp w(1,0); for (int j=0;j<mid;j++,w*=temp) { cp x=f[i+j],y=w*f[i+j+mid]; f[i+j]=x+y; f[i+j+mid]=x-y; } } } } int main() { scanf("%s",ch); n=strlen(ch); for (int i=0;i<n;i++) f[i]=cp(1.0*(ch[n-i-1]-48),0.0); scanf("%s",ch); m=strlen(ch); for (int i=0;i<m;i++) g[i]=cp(1.0*(ch[m-i-1]-48),0.0); n+=m; while (Maxn<=n) Maxn<<=1; for (int i=0;i<Maxn;i++) rev[i]=(rev[i>>1]>>1)|((i&1)?(Maxn>>1):0); fft(f,1); fft(g,1); for (int i=0;i<Maxn;i++) f[i]*=g[i]; fft(f,-1); for (int i=0;i<=Maxn;i++) { h[i]+=(int)(f[i].real()/Maxn+0.4999); if (i==Maxn && h[i]>9) Maxn++; h[i+1]=h[i]/10; h[i]%=10; } int i=Maxn; while (!h[i] && i) i--; for (;i>=0;i--) printf("%d",h[i]); return 0; }