zoukankan      html  css  js  c++  java
  • (FFT) A * B Problem Plus

    题目链接:https://cn.vjudge.net/contest/280041#problem/F

    题目大意:给你两个数,求这俩数相乘的结果。(长度最长5000)

    具体思路:硬算肯定是不行的,比如说1024*1234 ,我们可以将1024转换成 (4*10^0 + 2*10^1 +0*10^2+1*10^3),然后1234转换成(4*10^0+3*10^1+2*10^2+1*10^3),然后我们就可以转换成多项式相乘来保证计算精度了。

    AC代码:

    #include<iostream>
    #include<cmath>
    #include<stdio.h>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    # define ll long long
    const int mod = 1e9+7;
    const double PI = acos(-1.0);
    struct complex
    {
        double r,i;
        complex(double _r = 0,double _i = 0)
        {
            r = _r;
            i = _i;
        }
        complex operator +(const complex &b)
        {
            return complex(r+b.r,i+b.i);
        }
        complex operator -(const complex &b)
        {
            return complex(r-b.r,i-b.i);
        }
        complex operator *(const complex &b)
        {
            return complex(r*b.r-i*b.i,r*b.i+i*b.r);
        }
    };
    void change(complex y[],int len)
    {
        int i,j,k;
        for(i = 1, j = len/2; i < len-1; i++)
        {
            if(i < j)
                swap(y[i],y[j]);
            k = len/2;
            while( j >= k)
            {
                j -= k;
                k /= 2;
            }
            if(j < k)
                j += k;
        }
    }
    void fft(complex y[],int len,int on)
    {
        change(y,len);
        for(int h = 2; h <= len; h <<= 1)
        {
            complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
            for(int j = 0; j < len; j += h)
            {
                complex w(1,0);
                for(int k = j; k < j+h/2; k++)
                {
                    complex u = y[k];
                    complex t = w*y[k+h/2];
                    y[k] = u+t;
                    y[k+h/2] = u-t;
                    w = w*wn;
                }
            }
        }
        if(on == -1)
            for(int i = 0; i < len; i++)
                y[i].r /= len;
    }
    const int maxn = 2e5+100;//开数组的时候注意,长度的话至少是开两倍的,因为是两个数组相加的!!。
    complex x1[maxn],x2[maxn];
    char str1[maxn],str2[maxn];
    int sum[maxn];
    int main()
    {
        while(scanf("%s %s",str1,str2)==2)
        {
            int len1=strlen(str1);
            int len2=strlen(str2);
            int len=1;
            while(len<len1*2||len<len2*2)
                len<<=1;
            for(int i=0; i<len1; i++)
            {
                x1[i]=complex(str1[len1-1-i]-'0',0);
            }
            for(int i=len1; i<len; i++)
            {
                x1[i]=complex(0,0);
            }
            for(int i=0; i<len2; i++)
            {
                x2[i]=complex(str2[len2-1-i]-'0',0);
            }
            for(int i=len2; i<len; i++)
            {
                x2[i]=complex(0,0);
            }
            fft(x1,len,1);
            fft(x2,len,1);
            for(int i=0; i<len; i++)
            {
                x1[i]=x1[i]*x2[i];
            }
            fft(x1,len,-1);
            for(int i=0; i<len; i++)
            {
                sum[i]=(int)(x1[i].r+0.5);
            }
            for(int i=0; i<len; i++)
            {
                sum[i+1]+=sum[i]/10;
                sum[i]%=10;
            }
            len=len1+len2-1;
            while(sum[len]<=0&&len>0)
                len--;
            for(int i=len; i>=0; i--)
            {
                printf("%c",sum[i]+'0');
            }
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    (转)轻松应对IDC机房带宽突然暴涨问题
    (转)老男孩:Linux企业运维人员最常用150个命令汇总
    (转)cut命令详解
    (转)Awk使用案例总结(运维必会)
    (转)Nmap命令的29个实用范例
    BigPipe学习研究
    js正则大扫除
    ffff表单提交的那点事
    高并发订单操作处理方法
    订单号的处理
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10300835.html
Copyright © 2011-2022 走看看