Description
给出两个n位10进制整数x和y,你需要计算x*y。
【题目分析】
FFT裸题用来快速计算高精度的乘法,从n^2变成了n。其实不会,随便抄了一个模板。以后再慢慢学。
【代码】
#include<bits/stdc++.h>
using namespace std;
const double pi=acos(-1.0);
int rev[200001],ans[200001],len,n,m;
char s[200001];
struct P
{
double x,y;
inline P operator +(P a) {return (P){x+a.x,y+a.y};}
inline P operator -(P a) {return (P){x-a.x,y-a.y};}
inline P operator *(P a) {return (P){x*a.x-y*a.y,x*a.y+y*a.x};}
}a[200001],b[200001],c[200001];
inline void fft(P *x,int n,int flag)//快速傅立叶变换
{
for (int i=0;i<n;++i) if (rev[i]>i) swap(x[rev[i]],x[i]);
for(int m=2;m<=n;m<<=1)
{
P wn=(P){cos(2.0*pi/m*flag),sin(2.0*pi/m*flag)};
for(int i=0;i<n;i+=m)
{
P w=(P){1.0,0};int mid=m>>1;
for (int j=0;j<mid;++j)
{
P u=x[i+j],v=x[i+j+mid]*w;
x[i+j]=u+v;x[i+j+mid]=u-v;
w=w*wn;
}
}
}
}
int main()
{
scanf("%d",&n);
scanf("%s",s);for (int i=0;i<n;++i) a[i].x=s[n-i-1]-'0';
scanf("%s",s);for (int i=0;i<n;++i) b[i].x=s[n-i-1]-'0';
m=1;n=n*2-1;
while (m<=n) m<<=1,len++; n=m;
for (int i=0;i<n;++i)
{
int t=i,ret=0;
for (int j=1;j<=len;++j) ret<<=1,ret|=t&1,t>>=1;
rev[i]=ret;
}
fft(a,n,1);fft(b,n,1);//转过去
for (int i=0;i<n;++i) c[i]=a[i]*b[i];//高效率高精度
fft(c,n,-1);//又回来
for (int i=0;i<n;++i) ans[i]=(c[i].x/n)+0.5;//精度误差
for (int i=0;i<n;++i) ans[i+1]+=ans[i]/10,ans[i]%=10;//进位
n++;
while (!ans[n]&&n) n--;//确定第一个数的位置
for (int i=n;i>=0;--i) putchar(ans[i]+'0');//输出
}