FFT 求a * b

输入两个长度在5000005内的整数a,b,输出a*b的值

#include<cstdio>

#include<cmath>

#include<cstring>

#include<algorithm>

using namespace std;

const int N =500005;

const double pi = acos(-1.0);

char s1[N],s2[N];

int len,res[N];

struct Complex

{

    double r,i;

    Complex(double r=0,double i=0):r(r),i(i) {};

    Complex operator+(const Complex &rhs)

    {

        return Complex(r + rhs.r,i + rhs.i);

    }

    Complex operator-(const Complex &rhs)

    {

        return Complex(r - rhs.r,i - rhs.i);

    }

    Complex operator*(const Complex &rhs)

    {

        return Complex(r*rhs.r - i*rhs.i,i*rhs.r + r*rhs.i);

    }

} va[N],vb[N];

void rader(Complex F[],int len)//len = 2^M,reverse F[i] with  F[j] ji二进制反转

{

    int j = len >>1;

    for(int i =1;i < len -1;++i)

    {

        if(i < j) swap(F[i],F[j]); // reverse

        int k = len>>1;

        while(j>=k)

        {

            j -= k;

            k >>= 1;

        }

        if(j < k) j += k;

    }

}

void FFT(Complex F[],int len,int t)

{

    rader(F,len);

    for(int h=2;h<=len;h<<=1)

    {

        Complex wn(cos(-t*2*pi/h),sin(-t*2*pi/h));

        for(int j=0;j<len;j+=h)

        {

            Complex E(1,0);//旋转因子

            for(int k=j;k<j+h/2;++k)

            {

                Complex u = F[k];

                Complex v = E*F[k+h/2];

                F[k] = u+v;

                F[k+h/2] = u-v;

                E=E*wn;

            }

        }

    }

    if(t==-1)  //IDFT

        for(int i=0;i<len;++i)

            F[i].r/=len;

}

void Conv(Complex a[],Complex b[],int len)//求卷积

{

    FFT(a,len,1);

    FFT(b,len,1);

    for(int i=0;i<len;++i) a[i] = a[i]*b[i];

    FFT(a,len,-1);

}

void init(char *s1,char *s2)

{

    int n1 = strlen(s1),n2 = strlen(s2);

    len = 1;

    while(len <2*n1 || len <2*n2) len <<=1;

    int i;

    for(i=0;i<n1;++i)

    {

        va[i].r = s1[n1-i-1]-'0';

        va[i].i =0;

    }

    while(i<len)

    {

        va[i].r =va[i].i =0;

        ++i;

    }

    for(i=0;i<n2;++i)

    {

        vb[i].r = s2[n2-i-1]-'0';

        vb[i].i =0;

    }

    while(i<len)

    {

        vb[i].r =vb[i].i =0;

        ++i;

    }

}


void gao()

{

    Conv(va,vb,len);

    memset(res,0,sizeof(res));

    for(int i=0;i<len;++i)

    {

        res[i]=va[i].r +0.5;

    }

    for(int i=0;i<len;++i)

    {

        res[i+1]+=res[i]/10;

        res[i]%=10;

    }

    int high =0;

    for(int i=len-1;i>=0;--i)

    {

        if(res[i])

        {

            high = i;

            break;

        }

    }

    for(int i=high;i>=0;--i)putchar('0'+res[i]);

    puts("");

}

int main()

{

    while(scanf("%s %s",s1,s2)==2)

    {

        init(s1,s2);

        gao();

    }

    return 0;

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值