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

 

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

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=2e5+5;
const double Pi=acos(-1);

int n,m;
int rev[N];
char s[N];
int bit,len=1;
struct Complex
{
    double x,y;
    Complex(double xx=0,double yy=0){x=xx,y=yy;}
    Complex operator + (const Complex &a)
    {
        return Complex(this->x + a.x,this->y + a.y);
    }
    Complex operator - (const Complex &a)
    {
        return Complex(this->x - a.x,this->y - a.y);
    }
    Complex operator * (const Complex &a)
    {
        return Complex(this->x * a.x - this->y * a.y, this->x * a.y + this->y * a.x);
    }
}a[N],b[N];

inline int read()
{
    char c=getchar();int num=0;
    for(;!isdigit(c);c=getchar());
    return c^'0';
}

void fft(Complex *A,int type)
{
    for(int i=0;i<len;++i)
        if(i<rev[i])
            swap(A[i],A[rev[i]]);
    for(int step=1;step<len;step<<=1)
    {
        Complex wn(cos(Pi/step),type*sin(Pi/step));
        for(int j=0;j<len;j+=step<<1)
        {
            Complex wnk(1,0);
            for(int k=j;k<step+j;++k)
            {
                Complex x=A[k];
                Complex y=wnk*A[k+step];
                A[k]=x+y;
                A[k+step]=x-y;
                wnk=wnk*wn;
            }
        }
    }
}

int ans[N];
int main()
{
    scanf("%d",&n);
    for(int i=n-1;i>=0;--i)
        a[i].x=read();
    for(int i=n-1;i>=0;--i)
        b[i].x=read();
    while(len<=n*2)
        len<<=1,++bit;
    for(int i=0;i<len;++i)
        rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
    fft(a,1);
    fft(b,1);
    for(int i=0;i<=len;++i)
        a[i]=a[i]*b[i];
    fft(a,-1);
    int front=0,R=n<<1;
    for(;(int)(a[R].x/len+0.5)==0;--R);
    for(int i=0;i<=R;++i)
        ans[i]=(int)(a[i].x/len+0.5);
    for(int i=0;i<=R;++i)
    {
        if(ans[i]>=10)
        {
            ans[i+1]+=ans[i]/10;
            ans[i]%=10;
        }
    }
    if(ans[R+1])
        ++R;
    for(int i=R;i>=0;--i)
        printf("%d",ans[i]);
    return 0;
}

/*
10 
9789344841 
4839019669 

47370832232222677629
*/

 

posted @ 2018-05-01 21:17  whymhe  阅读(315)  评论(0编辑  收藏  举报