BZOJ2179 - FFT快速傅立叶
Description
给出两个\(n(n\leq6\times10^4)\)位的正整数\(x,y\),求\(x\times y\)。
Solution
令\(a_i,b_i\)分别表示\(x,y\)从低到高的第\(i\)位,\(f_1(x)=\sum_{i=0}^{n-1}a_ix^i,f_2(x)=\sum_{i=0}^{n-1}b_ix_i\)。则\(x=f_1(10),y=f_2(10)\)。做多项式乘法并进位即可。
时间复杂度\(O(nlogn)\)。
Code
//FFT快速傅立叶
#include <complex>
#include <cstdio>
using namespace std;
typedef complex<double> cpx;
int const N=2e5+10;
double const PI=acos(-1);
int n,t; char s[N];
cpx a[N],b[N],c[N];
int pos[N];
void FFT(cpx x[],int f)
{
for(int i=0;i<t;i++) if(i<pos[i]) swap(x[i],x[pos[i]]);
for(int i=1;i<t;i<<=1)
{
cpx Wn=cpx(cos(PI/i),f*sin(PI/i));
for(int j=0;j<t;j+=i<<1)
{
cpx w=1;
for(int k=0;k<i;k++,w*=Wn)
{
cpx p=x[j+k],q=w*x[j+k+i];
x[j+k]=p+q,x[j+k+i]=p-q;
}
}
}
if(f==-1) for(int i=0;i<t;i++) x[i]/=t;
}
int ans[N];
int main()
{
scanf("%d",&n);
scanf("%s",s); for(int i=0;i<n;i++) a[i]=s[n-i-1]-'0';
scanf("%s",s); for(int i=0;i<n;i++) b[i]=s[n-i-1]-'0';
t=1; int n0=0; while(t<=n+n) t<<=1,n0++;
for(int i=0;i<t;i++) pos[i]=(pos[i>>1]>>1)|((i&1)<<(n0-1));
FFT(a,1),FFT(b,1);
for(int i=0;i<t;i++) c[i]=a[i]*b[i];
FFT(c,-1);
for(int i=0;i<t;i++) ans[i]=(int)(c[i].real()+0.5);
for(int i=0;i<t;i++) ans[i+1]+=ans[i]/10,ans[i]%=10;
while(!ans[t]) t--;
for(int i=t;i>=0;i--) printf("%d",ans[i]);
puts("");
return 0;
}
P.S.
名字暴露一切