【bzoj2179】FFT快速傅立叶

来源:互联网 发布:一览php英才网 编辑:程序博客网 时间:2024/05/01 02:26

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然后乘起来,再做一次DTF1就好了,简直水。

代码

#include <bits/stdc++.h>#define N 131072#define pi acos(-1)#define ll long longtypedef 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");       }
0 0