题目描述
给出两个n位10进制整数x和y,你需要计算x*y。
输入输出格式
输入格式:
第一行一个正整数n。 第二行描述一个位数为n的正整数x。 第三行描述一个位数为n的正整数y。
输出格式:
输出一行,即x*y的结果。(注意判断前导0)
输入输出样例
输入样例#1:
1
3
4
输出样例#1:
12
说明
数据范围:
n<=60000
来源:bzoj2179
分析:可以把一个正整数看做是一个多项式,其中x=10(其实也可以是10^k),然后跑fft,跑出来之后好进行进位处理。
扫描二维码关注公众号,回复:
890267 查看本文章
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
const int maxn=240007;
const double pi=acos(-1);
using namespace std;
struct rec{
double x,y;
};
rec operator + (rec a,rec b) {return (rec){a.x+b.x,a.y+b.y};}
rec operator - (rec a,rec b) {return (rec){a.x-b.x,a.y-b.y};}
rec operator * (rec a,rec b) {return (rec){a.x*b.x-a.y*b.y,a.y*b.x+a.x*b.y};}
rec a[maxn],b[maxn];
char s[maxn];
int r[maxn],ans[maxn];
int n,l,p;
void fft(rec *a,int f)
{
for (int i=0;i<l;i++)
{
if (i<r[i]) swap(a[i],a[r[i]]);
}
for (int i=2;i<=l;i*=2)
{
rec wn=(rec){cos(2*pi/i),f*sin(2*pi/i)};
for (int j=0;j<l;j+=i)
{
rec w=(rec){1,0};
for (int k=0;k<i/2;k++)
{
rec u=a[j+k],v=w*a[j+k+i/2];
a[j+k]=u+v;
a[j+k+i/2]=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';
l=1;p=0;
while (l<(n*2)) l*=2,p++;
for (int i=0;i<l;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(p-1));
fft(a,1);
fft(b,1);
for (int i=0;i<l;i++) a[i]=a[i]*b[i];
fft(a,-1);
int num;
for (int i=0;i<l+3;i++)
{
ans[i]=ans[i]+trunc(a[i].x/l+0.233);
if (ans[i]>0) num=i;
ans[i+1]=ans[i]/10;
ans[i]=ans[i]%10;
}
for (int i=num;i>=0;i--) printf("%d",ans[i]);
}