HDU 1402 A * B Problem Plus (快速傅里叶变换实现大数乘法)

本文介绍了一种使用快速傅里叶变换(FFT)来实现大数乘法的方法,并提供了详细的AC代码示例。该方法通过将大数转换为多项式系数表示,利用FFT进行高效卷积计算,有效解决了传统乘法在处理大数时效率低下的问题。





http://acm.hdu.edu.cn/showproblem.php?pid=1402







分析:  

用fft实现的大数乘法      稍微注意一下进位就好了



AC代码:

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include<list>
#include <bitset>
#include <climits>
#include <algorithm>
#define gcd(a,b) __gcd(a,b)
#define FIN	freopen("input.txt","r",stdin)
#define FOUT 	freopen("output.txt","w",stdout)
typedef long long ll;
const ll mod=1e9+7;
const ll INF=0x3f3f3f3f;
const double PI=acos(-1.0);
using namespace std;
char str1[100005],str2[100005];
int ans[200010];
struct complex{//            运算符重载
    double a,b;
    complex(double a=0.0,double b=0.0){this->a=a;this->b=b;}
    complex operator + (complex &p){return complex(a+p.a,b+p.b);}
    complex operator - (complex &p){return complex(a-p.a,b-p.b);}
    complex operator * (complex &p){return complex(a*p.a-b*p.b,a*p.b+b*p.a);}
}x[200010],y[200010];
void Rader(complex a[],int len){//       倒位序
    int k;
    for (int i=1,j=len/2;i<len-1;i++){
        if(i<j) swap(a[i],a[j]);
        k=len/2;
        while (j>=k){
            j-=k;
            k/=2;
        }
        if(j<k) j+=k;
    }
}
void fft(complex a[],int len,int oper){//                     快速傅里叶变换
    Rader(a,len);//     对a进行倒位序
    for (int h=2;h<=len;h<<=1){
        complex wn(cos(-oper*2*PI/h),sin(-oper*2*PI/h));
        for (int j=0;j<len;j+=h){
            complex w(1,0);
            for (int k=j;k<j+h/2;k++){
                complex u=a[k];
                complex t=w*a[k+h/2];
                a[k]=u+t;
                a[k+h/2]=u-t;
                w=w*wn;
            }
        }
    }
    if(oper==-1)
    for (int i=0;i<len;i++)
        a[i].a/=len;
}
int main (){
    while (scanf ("%s%s",str1,str2)!=EOF){
        memset(ans,0,sizeof(ans));
        memset(x,0,sizeof(x));
        memset(y,0,sizeof(y));
        int len1=strlen(str1);
        int len2=strlen(str2);
        int len=1;
        while (len<2*len1||len<2*len2)  len<<=1;
        for (int i=0;i<len1;i++){
            x[i]=complex(str1[len1-1-i]-'0');
        }
        for (int i=0;i<len2;i++){
            y[i]=complex(str2[len2-i-1]-'0');
        }
        fft(x,len,1);
        fft(y,len,1);
        for (int i=0;i<len;i++)
            x[i]=x[i]*y[i];
        fft(x,len,-1);
        for (int i=0;i<len;i++){
            ans[i]=(int)(x[i].a+0.5);
        }
        for (int i=0;i<len;i++){//     进位
            ans[i+1]+=ans[i]/10;
            ans[i]%=10;
        }
        int i=len;
        while (ans[i]<=0&&i>0)
            i--;
        for (int k=i;k>=0;k--)//      倒序输出
            printf ("%d",ans[k]);
        putchar('\n');
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值