【HDU 1402】A * B Problem Plus(FFT)

Problem Description


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

题解


做卷积主要思想是,先把系数表达式转化为点值表达式,而点值表达式相乘的时间复杂度是\(O(n)\)的,唯一需要优化的是这个转化的过程,需要使用fft进行优化,时间负责度可以降为\(O(nlogn)\),具体算法思想参看
资料:http://blog.csdn.net/iamzky/article/details/22712347

参考代码

#include <queue>
#include <cmath>
#include <cstdio>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ll long long
#define inf 1000000000
#define PI acos(-1)
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void Out(ll a){
    if(a<0) putchar('-'),a=-a;
    if(a>=10) Out(a/10);
    putchar(a%10+'0');
}
const int N=200005;
typedef complex<double> E;
E a[N],b[N],A[N],c[N];
char s1[N],s2[N];
int sum[N],a1[N],a2[N],dig[N],rev[N];
void FFT(E a[],int n,int flag){
    E x,y;
    for(int i=0;i<n;i++) A[i]=a[rev[i]];
    for(int i=0;i<n;i++) a[i]=A[i];
    for(int i=2;i<=n;i<<=1){
        E wn(cos(2*PI/i),flag*sin(2*PI/i));
        for(int k=0;k<n;k+=i){
            E w(1,0);
            for(int j=k;j<k+i/2;j++){
                x=a[j];
                y=a[j+i/2]*w;
                a[j]=x+y;
                a[j+i/2]=x-y;
                w=w*wn;
            }
        }
    }
    if(flag==-1) for(int i=0;i<n;i++) a[i]/=n;
}
int main(){
    while(~scanf("%s%s",s1,s2)){
        int len1=strlen(s1),len2=strlen(s2),n,L;
        for(n=1,L=0;n<max(len1,len2);n<<=1,L++);
        n<<=1;L++;
        mem(rev,0);mem(dig,0);
        mem(a1,0);mem(a2,0);
        for(int i=0;i<n;i++){
            int len=0;
            for(int t=i;t;t>>=1) dig[len++]=t&1;
            for(int j=0;j<L;j++) rev[i]=(rev[i]<<1)|dig[j];
        }
        for(int i=0;i<len1;i++) a1[len1-i-1]=s1[i]-'0';
        for(int i=0;i<len2;i++) a2[len2-i-1]=s2[i]-'0';
        for(int i=0;i<n;i++) a[i]=E(a1[i]);
        for(int i=0;i<n;i++) b[i]=E(a2[i]);
        FFT(a,n,1);FFT(b,n,1);
        for(int i=0;i<n;i++) c[i]=a[i]*b[i];
        FFT(c,n,-1);
        for(int i=0;i<n;i++) sum[i]=c[i].real()+0.5;
        for(int i=0;i<n;i++){
            sum[i+1]+=sum[i]/10;
            sum[i]%=10;
        }
        int l=len1+len2-1;
        while(sum[l]==0&&l>0)l--;
        for(int i=l;i>=0;i--)
            putchar(sum[i]+'0');
        putchar('\n');
    }
    return 0;
}
posted @ 2017-07-19 10:35  江南何采莲  阅读(140)  评论(0编辑  收藏  举报