zoukankan      html  css  js  c++  java
  • 【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。
    
  • 相关阅读:
    每天一个linux命令(25):linux文件属性详解
    每天一个linux命令(24):Linux文件类型与扩展名
    每天一个linux命令(23):Linux 目录结构
    每天一个linux命令(22):find 命令的参数详解
    每天一个linux命令(21):find命令之xargs
    每天一个linux命令(20):find命令之exec
    每天一个linux命令(19):find 命令概览
    Unity3D自己常用代码
    Unity导入FBX自动进行动画切分
    Unity和虚幻的比较
  • 原文地址:https://www.cnblogs.com/hiweibolu/p/6714793.html
Copyright © 2011-2022 走看看