【51NOD1028】大数乘法 V2

╰( ̄▽ ̄)╭

给出2个大整数A,B,计算A*B的结果。
(A,B的长度 <= 100000,A,B >= 0)

(⊙ ▽ ⊙)

把大整数A看做一个次数界lenA的多项式A(x),其中x=10
同样,把B看做一个次数界lenB的多项式B(x),其中x=10

然后套上快速傅里叶变换

( ̄~ ̄)

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
const char* fin="ftt.in";
const char* fout="fttx.out";
const int inf=0x7fffffff;
const double pi=acos(-1),eps=10e-6;
const int maxn=400007;
struct Z{
    double x,y;
    Z(double _x=0,double _y=0){x=_x;y=_y;}
    Z operator +(const Z &b){return Z(x+b.x,y+b.y);}
    Z operator -(const Z &b){return Z(x-b.x,y-b.y);}
    Z operator *(const Z &b){return Z(x*b.x-y*b.y,x*b.y+y*b.x);}
}a[maxn],b[maxn],t[maxn];
int ans[maxn],lena,lenb,n,N,i,j,k;
void read(Z *a,int &len){
    int i,j,k;
    char ch=getchar();
    while (ch<'0' || ch>'9') ch=getchar();
    while (ch>='0' && ch<='9') a[len++]=ch-'0',ch=getchar();
    for (i=0;i<(len+1)/2;i++) swap(a[i],a[len-i-1]);
}
void getn(){
    int i,j,k=max(lena,lenb);
    for (n=1;n<k;n<<=1) N++;
    n<<=1;N++;
}
int fan(int v){
    int i=N,k=0;
    while (i--){
        k=(k<<1)+(v&1);
        v>>=1;
    }
    return k;
}
void fft(Z *a,int sig){
    int i,j,k,m;
    for (i=0;i<n;i++) t[fan(i)]=a[i];
    for (m=2;m<=n;m<<=1){
        int ha=m/2;
        for (i=0;i<ha;i++){
            Z w(cos(i*sig*pi/ha),sin(i*sig*pi/ha));
            for (j=i;j<n;j+=m){
                Z u=t[j],v=w*t[j+ha];
                t[j]=u+v;
                t[j+ha]=u-v;
            }
        }
    }
    for (i=0;i<n;i++) a[i]=t[i];
}
int main(){
    freopen(fin,"r",stdin);
    freopen(fout,"w",stdout);
    read(a,lena);read(b,lenb);
    getn();

    fft(a,1);
    fft(b,1);
    for (i=0;i<n;i++) a[i]=a[i]*b[i];
    fft(a,-1);

    for (i=0;i<=n;i++){
        ans[i]+=int(a[i].x/n+eps);
        ans[i+1]+=ans[i]/10;
        ans[i]%=10;
    }
    while (!ans[n]) n--;
    for (;n>=0;n--) printf("%d",ans[n]);
    return 0;
}

(⊙v⊙)

Pay Attention

1.read()中,不要把len打成lena;
翻转大整数时,是从0枚举到(len+1)/2;

2.getn()中,n最后要再乘一次2,因为:
A*B的次数界是lena*lenb。

3.maxn要开到4倍;

4.pi=acos(-1);

5.当对一个小数x用int()取整时,需要打成int(x+eps),其中,eps=10e-6。
posted @ 2017-02-16 17:29  hiweibolu  阅读(129)  评论(0编辑  收藏  举报