Description
给出两个n位10进制整数x和y,你需要计算x*y。
Input
第一行一个正整数n。 第二行描述一个位数为n的正整数x。 第三行描述一个位数为n的正整数y。
Output
输出一行,即x*y的结果。
Sample Input
1
3
4
Sample Output
12
数据范围:
n<=60000
分析
看题目可知,这是一道裸的快速傅立叶变换,先对第一个数做一次DFT,再对第二个数做一次DFT然后乘起来,再做一次 DTF−1 就好了,简直水。
代码
#include <bits/stdc++.h>
#define N 131072
#define pi acos(-1)
#define ll long long
typedef std::complex<double> E;
E a[N],b[N];
int n,m,l;
int bRev[N];
int sum[N];
char ch[N];
void bitRev()
{
for(int i=0;i<n;i++)
bRev[i]=(bRev[i>>1]>>1)|((i&1)<<(l-1));
}
void fft(E *a,int f)
{
for(int i=0;i<n;i++)
if(i<bRev[i])
std::swap(a[i],a[bRev[i]]);
for(int i=1;i<n;i<<=1)
{
E wn(cos(pi/i),f*sin(pi/i));
for(int j=0;j<n;j+=(i<<1))
{
E w(1,0);
for(int k=0;k<i;k++)
{
E t=a[j+k];
E u=w*a[k+j+i];
a[j+k]=u+t;
a[i+j+k]=t-u;
w*=wn;
}
}
}
if(f==-1)
{
for(int i=0;i<n;i++)
a[i]/=n;
}
}
int main()
{
scanf("%d",&n);
n--;
scanf("%s",ch);
for(int i=0;i<=n;i++)
a[i]=ch[n-i]-'0';
scanf("%s",ch);
for(int i=0;i<=n;i++)
b[i]=ch[n-i]-'0';
m=n*2;
for(n=1;n<=m;n<<=1)
l++;
bitRev();
fft(a,1);
fft(b,1);
for(int i=0;i<=n;i++)
a[i]*=b[i];
fft(a,-1);
for(int i=0;i<=m;i++)
sum[i]=(int)(a[i].real()+0.1);
for(int i=0;i<=m;i++)
if(sum[i]>=10)
{
sum[i+1]+=sum[i]/10;
sum[i]%=10;
if(i==m)
m++;
}
for(int i=m;i>=0;i--)
printf("%d",sum[i]);
printf("\n");
}