P1919【模板】A*B Problem升级版(FFT快速傅里叶)

P1919 【模板】A*B Problem升级版(FFT快速傅里叶)

题目描述

给出两个n位10进制整数x和y,你需要计算x*y。

输入输出格式

输入格式:

 

第一行一个正整数n。 第二行描述一个位数为n的正整数x。 第三行描述一个位数为n的正整数y。

 

输出格式:

 

输出一行,即x*y的结果。(注意判断前导0)

 

输入输出样例

输入样例#1: 复制
1
3
4
输出样例#1: 复制
12

说明

数据范围:

n<=60000

来源:bzoj2179

本题数据为洛谷自造数据,使用CYaRon耗时5分钟完成数据制作。

 

只有70。。。懒得调了

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<complex>
#define N 131072
#define pi acos(-1)
using namespace std;
typedef complex<double> E;
int read()
{
    int x,f=1;char s=getchar();
    while(s>'9' || s<'0'){if(s=='-')f=-1;s=getchar();}
    while(s<='9' && s>='0'){x=x*10+s-'0';s=getchar();}
    return x*f;
}
char sa[N],sb[N];
E a[N],b[N];
int re[N],c[N],n,m,L;
void fft(E *a,int f)
{
    for(int i=0;i<m;i++)if(i<re[i])swap(a[i],a[re[i]]);
    for(int i=1;i<m;i<<=1)
    {
        E wn(cos(pi/i),f*sin(pi/i));
        for(int j=0;j<m;j+=(i<<1))
        {
            E w(1,0);
            for(int k=0;k<i;k++,w*=wn)
            {
                E x=a[j+k],y=w*a[j+k+i];
                a[j+k]=x+y;a[j+k+i]=x-y;
            }
        }
    }
    if(f==-1)for(int i=0;i<m;i++)a[i]/=m;
}
int main()
{
    n=read();n--;
    scanf("%s",sa);scanf("%s",sb);
    for(int i=0;i<=n;i++)a[i]=sa[n-i]-'0',b[i]=sb[n-i]-'0';
    //for(int i=0;i<=n;i++)printf("%d",(int)(a[i].real()+0.1));
    
    
    n<<=1;for(m=1;m<=n;m<<=1)L++;L--;
    for(int i=0;i<m;i++)re[i]=(re[i>>1]>>1)|((i&1)<<L);
    fft(a,1);fft(b,1);
    for(int i=0;i<m;i++)a[i]=a[i]*b[i];
    fft(a,-1);
    
    
    for(int i=0;i<=m;i++)c[i]=(int)(a[i].real()+0.1);
    for(int i=0;i<=m;i++)
        if(c[i]>=10)
        {
            c[i+1]+=c[i]/10,c[i]%=10;
            if(i==m)m++;
        }
    while(!c[m])m--;
    for(int i=m;i>=0;i--)printf("%d",c[i]);
    return 0;
}

 

posted @ 2018-03-27 20:11  hyf20010101  阅读(171)  评论(0编辑  收藏  举报