Live2d Test Env

HDU1402:A * B Problem Plus(FFT与大数乘法)

 

Calculate A * B. 
Input
  Each line will contain two integers A and B. Process to end of file. 

Note: the length of each integer will not exceed 50000. 
Output
  For each case, output A * B in one line. 
Sample Input
1
2
1000
2
Sample Output
2
2000

把每一位看成ai*10^i,然后就是两个多项式相乘。利用FFT,把复杂度降到O(nlogn)。

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=200010;
const double pi=acos(-1.0);
struct complex
{
    double r,i;
    complex(){};
    complex(double rr,double ii):r(rr),i(ii){}
    complex friend operator +(complex a,complex b){ return complex(a.r+b.r,a.i+b.i); }
    complex friend operator -(complex a,complex b) { return complex(a.r-b.r,a.i-b.i);}
    complex friend operator *(complex a,complex b) { return complex(a.r*b.r-a.i*b.i,a.r*b.i+a.i*b.r);}
}tmp[maxn];
struct DFT{
    complex a[maxn];
    void fft(int sz,int bg,int step,int opt){
       if(sz==1) return;  int m=sz>>1;
       fft(m,bg,step<<1,opt); fft(m,bg+step,step<<1,opt);
       complex w=complex(1,0),t=complex(cos(2.0*pi/sz),sin(2.0*pi*opt/sz)); 
       for(int k=0;k<m;k++)
       {
            int pos=2*step*k;
          tmp[k]=a[pos+bg]+w*a[pos+bg+step];
          tmp[k+m]=a[pos+bg]-w*a[pos+bg+step];
          w=w*t;
       }
       for(int i=0;i!=sz;i++) a[i*step+bg]=tmp[i];
    }
}A,B;
char c[maxn]; int ans[maxn+10];
int main()
{
    while(~scanf("%s",c)){    
        int L1=strlen(c),L2,len=1;
        for(int i=0;i<L1;i++) A.a[i].r=c[L1-i-1]-'0',A.a[i].i=0;
        scanf("%s",c);  L2=strlen(c);
        for(int i=0;i<L2;i++) B.a[i].r=c[L2-i-1]-'0',B.a[i].i=0;
        
        while(len<L1+L2+2) len<<=1;
        
        for(int i=L1;i<=len;i++) A.a[i].r=A.a[i].i=0;
        for(int i=L2;i<=len;i++) B.a[i].r=B.a[i].i=0;
        
        A.fft(len,0,1,1); B.fft(len,0,1,1);
        for(int i=0;i<len;i++) A.a[i]=A.a[i]*B.a[i];
        A.fft(len,0,1,-1);
        
        int head=0;
        for(int i=0;i<len;i++) ans[i]=(int)(A.a[i].r/len+0.5);
        for(int i=0;i<len;i++){
            ans[i+1]+=ans[i]/10; ans[i]%=10;
            if(ans[i]>0) head=i;
        }
        
        for(int i=head;i>=0;i--) printf("%d",ans[i]);
        printf("\n");
    }
    return 0;
}

 

posted @ 2018-04-05 17:23  nimphy  阅读(203)  评论(0编辑  收藏  举报