hdu 1402 A * B Problem Plus 【快速傅里叶变换FFT】

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

这道题用FFT解决大数乘法问题,比字符串模拟的大数乘法效率要高,听说还有更加快的数论解法;

马上就要学快速福利叶变换了,到时候再补充题解

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <queue>
using namespace std;
template <class T> void checkmin(T &t,T x) {if(x < t) t = x;}
template <class T> void checkmax(T &t,T x) {if(x > t) t = x;}
template <class T> void _checkmin(T &t,T x) {if(t==-1) t = x; if(x < t) t = x;}
template <class T> void _checkmax(T &t,T x) {if(t==-1) t = x; if(x > t) t = x;}
typedef pair <int,int> PII;
typedef pair <double,double> PDD;
typedef long long ll;
#define foreach(it,v) for(__typeof((v).begin()) it = (v).begin(); it != (v).end ; it ++)
const double Pi = acos(-1.0);
const int N = 200020;
struct vir {
    double re , im;
    vir(double a=0,double b=0) {re=a;im=b;}
    vir operator + (const vir &b) {return vir(re+b.re,im+b.im);}
    vir operator - (const vir &b) {return vir(re-b.re,im-b.im);}
    vir operator * (const vir &b) {return vir(re*b.re-im*b.im,re*b.im+im*b.re);}
};
vir x1[N] , x2[N];
void change(vir *x,int len,int loglen) {
    int i , j , k , t;
    for(i=0;i<len;i++) {
        t = i;
        for(j=k=0;j<loglen;j++,t>>=1)
            k=(k<<1)|(t&1);
        if(k < i) {
            vir tt = x[k]; x[k] = x[i]; x[i] = tt;
        }
    }
}
void fft(vir *x,int len,int loglen) {
    change(x , len , loglen);
    for(int i=0,t=1;i<loglen;i++,t<<=1) {
        int s = 0 , e = s + t;
        while(s < len) {
            vir a , b , wo(cos(Pi/t),sin(Pi/t)),wn(1,0);
            for(int j=s;j<s+t;j++) {
                a = x[j]; b = x[j+t] * wn;
                x[j] = a+b; x[j+t] = a-b;
                wn = wn * wo;
            }
            s = e + t; e = s + t;
        }
    }
}
void dit_fft(vir *x,int len,int loglen) {
    for(int i=0,s,e,t=1<<loglen;i<loglen;i++) {
        t>>=1; s=0; e=s+t;
        while(s < len) {
            vir a , b , wn(1,0) , wo(cos(Pi/t),-sin(Pi/t));
            for(int j=s;j<s+t;j++) {
                a=x[j]+x[j+t];b=(x[j]-x[j+t])*wn;
                x[j] = a; x[j+t] = b; wn = wn*wo;
            }
            s = e + t; e = s + t;
        }
    }
    change(x , len , loglen);
    for(int i=0;i<len;i++) x[i].re /= len;
}

void solve(char *a,char *b) {
    int i,len1,len2,len,loglen;
    int t , over;
    len1 = strlen(a)<<1 ; len2 = strlen(b)<<1;
    len = 1 ; loglen = 0;
    while(len < len1) len<<=1,loglen++;
    while(len < len2) len<<=1,loglen++;
    // init
    for(i=0;a[i];i++) x1[i].re=a[i]-'0',x1[i].im=0;
    for(;i<len;i++) x1[i].re=x1[i].im=0;
    for(i=0;b[i];i++) x2[i].re=b[i]-'0',x2[i].im=0;
    for(;i<len;i++) x2[i].re=x2[i].im=0;
    fft(x1,len,loglen);
    fft(x2,len,loglen);
    for(i=0;i<len;i++) x1[i]=x1[i]*x2[i];
    dit_fft(x1,len,loglen);
    //将x1.re从浮点数转化为十进制整型存入a
    for(i=(len1+len2)/2-2,over=len=0;i>=0;i--) {
        t=x1[i].re+over+0.5;
        a[len++] = t % 10;
        over = t / 10;
    }
    while(over) {
        a[len++] = over % 10;
        over /= 10;
    }
    // output
    for(len--;len>=0&&!a[len];len--);
    if(len < 0) putchar('0');
    else for(;len>=0;len--) putchar(a[len]+'0');
    puts("");
}
int main() {
    char a[N] , b[N];
    while(~scanf("%s%s",a,b)) {
        solve(a , b);
    }
    return 0;
}

 

posted @ 2013-03-30 03:01  aiiYuu  阅读(399)  评论(0编辑  收藏  举报