p1919 A*B Problem升级版
题目
给出两个n位10进制整数x和y,你需要计算x*y。
输入格式:
第一行一个正整数n。 第二行描述一个位数为n的正整数x。 第三行描述一个位数为n的正整数y。
输出格式:
输出一行,即x*y的结果。(注意判断前导0)
数据范围:
n<=60000
分析
将数字倒序读入,即个位数是1次方系数,十位数是2次方系数,以此类推。然后进行朴素的FFT,最后答案同样也倒序输出即可,注意输出地数应截止至2次方系数,因为1次方乘1次方得到的是2次方。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
#define pi acos(-1.0)
#define ri register int
int n,m,len,r[2100000];
inline int read(){
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s-'0');s=getchar();}
return x*f;
}
inline int read2(){
int f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
return (s-'0')*f;
}
struct node {
double x,y;
node(){};
node(double a,double b){x=a;y=b;}
}a[2100000],b[2100000];
inline node operator + (const node a,const node b){
return node(a.x+b.x,a.y+b.y);
}
inline node operator - (const node a,const node b){
return node(a.x-b.x,a.y-b.y);
}
inline node operator * (const node a,const node b){
return node(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);
}
inline void fft(node *a,int f){
for(ri i=0;i<n;i++)
if(i<r[i])
swap(a[i],a[r[i]]);
for(ri k=1;k<n;k<<=1){
node wn(cos(pi/k),sin(pi/k)*f);
for(ri i=0;i<n;i+=(k<<1)){
node w(1,0),p,q;
for(ri j=0;j<k;j++,w=w*wn){
p=a[i+j],q=a[i+j+k]*w;
a[i+j]=p+q,a[i+j+k]=p-q;
}
}
}
if(f==-1)
for(ri i=0;i<n;i++)
a[i].x=a[i].x/n;
}
int ans[2100000];
int main()
{ n=read();m=n;
a[0].x=b[0].x=0;
for(ri i=n;i>0;i--)a[i].x=read2();
for(ri i=m;i>0;i--)b[i].x=read2();
m+=n;
for(n=1;n<=m;n<<=1)len++;
for(ri i=0;i<n;i++)r[i]=((r[i>>1]>>1)|((i&1)<<(len-1)));
fft(a,1),fft(b,1);
for(ri i=0;i<n;i++)a[i]=a[i]*b[i];
fft(a,-1);
for(ri i=1;i<=m;i++)ans[i]=(int)(a[i].x+0.5);
for(ri i=1;i<=m;i++)
if(ans[i]>=10){
ans[i+1]+=(ans[i]/10);
ans[i]%=10;
}
int ok=0;
for(ri i=m+1;i>1;i--){
if(ans[i])ok=1;
if(ok)printf("%d",ans[i]);
}
return 0;
}