FFT就不多说了吧,反正已经有写得很好的blog了,强烈推荐去看menci的FFT学习笔记,写得十分详细,条理也很清晰,我就是看这个才懂FFT的!!(传送门:menci FFT学习笔记)
这里只是想提几个注意点。
[1] 蝴蝶操作需谨慎,就是将每个a[i]映射到对应位置的时候,由于二进制的位置从0开始标号,容易搞错;
[2] 自定义的operator运算最好加括号,防止优先级的问题
[3] 最后a[i]/n应该改成(a[i]+0.5)/n,因为由于精度误差,可能a[i]/n出现12.9999/13这种情况,导致整除的时候结果比原来小。
[4] 中途迭代的时候下标不能搞错,我一开始就把a[i+l]写成a[i]了。
FFT不容易调试,能读程序找错最好,不能的话只好出几个样例来看了,要细心一点。
#include <cstdio>
#include <cmath>
#include <cstring>
#define db double
#define rep(i,j,k) for (i=j;i<=k;i++)
#define down(i,j,k) for (i=j;i>=k;i--)
using namespace std;
const int N=12e5+5;
const db PI=acos(-1.0);
char sa[N],sb[N];
struct cpl{
db a,b;
cpl () { a=b=0; }
cpl (db aa,db bb) { a=aa; b=bb; }
cpl operator + (const cpl &B) { return cpl(a+B.a,b+B.b); }
cpl operator - (const cpl &B) { return cpl(a-B.a,b-B.b); }
cpl operator * (const cpl &B) { return cpl(a*B.a-b*B.b,a*B.b+b*B.a); }
}A[N],B[N],C[N];
struct large{
int n,d[N];
cpl a[N];
int pos(int x,int K)
{
int i,ret=0;
rep(i,0,K-1)
if (x&(1<<i)) ret+=(1<<(K-i-1));
return ret;
}
void FFT(cpl *A,int K,int sgn) //K-positions
{
int i,l,m,k,len=1<<K;
cpl bsc,w,L,R;
rep(i,0,len-1) a[pos(i,K)]=A[i];
for (k=2;k<=len;k<<=1)
{
m=k/2; bsc=cpl(cos(2*PI/k),sgn*sin(2*PI/k));
for (l=0;l<len;l+=k)
{
w=cpl(1,0);
rep(i,0,m-1)
{
L=a[l+i]; R=a[l+m+i];
a[l+i]=L+(w*R); //ÓÅÏȼ¶!!
a[l+i+m]=L-(w*R);
w=w*bsc;
}
}
}
rep(i,0,len-1)
if (sgn==1) A[i]=a[i];
else A[i]=cpl((a[i].a+0.5)/len,0); //·ÀÖ¹³öÏÖ12.99999ÕâÑùµÄ¾«¶ÈÎó²î,Òª+0.5
}
void mult (const large &Y,large &ret)
{
int i,k,len=n+Y.n-1;
for (k=0;(1<<k)<len;k++);
len=1<<k; //0~len-1
rep(i,0,len-1) A[i]=cpl(d[i],0),B[i]=cpl(Y.d[i],0);
FFT(A,k,1);
FFT(B,k,1);
rep(i,0,len-1) C[i]=A[i]*B[i];
FFT(C,k,-1); ret.n=len;
rep(i,0,len-1) ret.d[i]=C[i].a;
rep(i,0,ret.n-1)
{
if (ret.d[i]>9)
{
if (i==ret.n-1) ret.n++;
ret.d[i+1]+=ret.d[i]/10;
ret.d[i]%=10;
}
}
for (;ret.n>1 && !ret.d[ret.n-1];ret.n--);
}
}numA,numB,ans;
int n,i;
int main()
{
scanf("%d",&n); numA.n=numB.n=n;
scanf("%s%s",sa,sb);
rep(i,0,n-1) numA.d[i]=sa[n-i-1]-'0',numB.d[i]=sb[n-i-1]-'0';
numA.mult(numB,ans);
down(i,ans.n-1,0) printf("%d",ans.d[i]);
return 0;
}