A * B Problem Plus HDU - 1402 (FFT入门)

利用fft加速乘法,直接套模板就行。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long long ll;
const int MAXN= 2e5+10;
const int maxn=1e5+10;
const double PI = acos(-1.0);
struct Complex
{
    double x,y;
    inline Complex operator +(const Complex b)const {return (Complex){x+b.x,y+b.y};}
    inline Complex operator -(const Complex b)const {return (Complex){x-b.x,y-b.y}; }
    inline Complex operator *(const Complex b)const {return (Complex){x*b.x-y*b.y,x*b.y+y*b.x};}
}va[MAXN*2+MAXN/2],vb[MAXN*2+MAXN/2];
int lenth=1, rev[MAXN*2+MAXN/2];
int N, M; //f和g的数量
int f[MAXN], g[MAXN]; //f和g的系数
vector<LL> conv; //卷积结果
vector<LL> multi; //⼤数乘积
void init()
{
    int tim=0; lenth = 1;
    conv.clear(), multi.clear();
    memset( va , 0 , sizeof va);
    memset( vb , 0 , sizeof vb);
    while( lenth <= N+M-2 ) lenth<<=1,tim++;
    for( int i=0;i<lenth;i++)
        rev[i]=(rev[i>>1]>>1)+((i&1)<<(tim-1));
}
void FFT(Complex*A,const int fla)
{
    for( int i=0;i<lenth;i++)
    {
        if(i<rev[i])
        {
           swap(A[i],A[rev[i]]);
        }
    }
    for( int i=1;i<lenth;i<<=1)
    {
        const Complex w = (Complex){cos(PI/i),fla*sin(PI/i)};
        for( int j=0;j<lenth;j+=(i<<1))
        {
            Complex K=(Complex){1,0};
            for( int k=0;k<i;k++,K=K*w)
            {
                const Complex x=A[j+k],y=K*A[j+k+i];
                A[j+k]=x+y;
                A[j+k+i]=x-y;
            }
        }
    }
}
void getConv()
{
    init();
    for( int i = 0 ; i < N; i++ ) va[i].x = f[i];
    for( int i = 0 ; i < M ; i++) vb[i].x = g[i];
    FFT(va,1),FFT(vb,1);
    for( int i=0;i<lenth;i++) va[i]=va[i]*vb[i];
    FFT(va,-1);
    for( int i = 0; i <= N+M-2 ; i++) conv.push_back((LL)(va[i].x/lenth+0.5));
}
void getMulti()
{
    getConv();
    multi = conv;
    reverse(multi.begin(), multi.end());
    multi.push_back(0);
    for( int i = 0; i < multi.size()-1 ; i++)
    {
        multi[i+1] += multi[i]/10;
        multi[i] %= 10;
    }
    while(!multi.back() && multi.size() > 1) multi.pop_back();
    reverse(multi.begin(), multi.end());
}
//事先需要设置系数f和g和数组⼤⼩N和M
//卷积结果保存conv, 乘法结果保存mult
char s1[maxn],s2[maxn];
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    while(~scanf("%s%s",s1,s2))
    {
        N=strlen(s1),M=strlen(s2);
        for(int i=0;i<N;i++)
        {
            f[i]=s1[i]-'0';
        }
        for(int j=0;j<M;j++)
        {
            g[j]=s2[j]-'0';
        }
        getMulti();
        for(auto &t: multi)
        {
            printf("%d",t);
        }
        printf("\n");
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值