zoukankan      html  css  js  c++  java
  • BZOJ_2179_FFT快速傅立叶_(FFT)

    描述


    http://www.lydsy.com/JudgeOnline/problem.php?id=2179

    超大整数乘法

    分析


    FFT模板题.

    把数字看成是多项式,x是10.然后用FFT做多项式乘法,最后进位就好了.

    注意:

    1.进位前要把每一位加0.5(或者更小),然后向下取整,应该是浮点数的计算误差吧...

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn=140000;
     5 const double pi=acos(-1.0);
     6 int len;
     7 int rev[maxn],ans[maxn];
     8 char str[maxn];
     9 struct cp{//复数(complex)
    10     double r,i;
    11     cp(double r_=0.0,double i_=0.0):r(r_),i(i_){}
    12     cp operator + (const cp &x) const { return cp(r+x.r,i+x.i); }
    13     cp operator - (const cp &x) const { return cp(r-x.r,i-x.i); }
    14     cp operator * (const cp &x) const { return cp(r*x.r-i*x.i,r*x.i+i*x.r); }
    15 }a[maxn],b[maxn],A[maxn];
    16 void brc(int &len){//二进制逆序置换(bit-reverse-copy)
    17     memset(rev,-1,sizeof rev);
    18     int k=1,l=0;
    19     while(k<len) k<<=1,l++;
    20     len=k;
    21     rev[0]=0; rev[len-1]=len-1;
    22     for(int i=1;i<len-1;i++){
    23         if(rev[i]!=-1) continue;
    24         int x=i,y=0,m=l;
    25         while(m--) y<<=1, y|=(x&1), x>>=1;
    26         rev[i]=y; rev[y]=i;
    27     }
    28 }
    29 void dft(cp *a,int n,int flag){//离散傅里叶变换(discrete-Fourier-transform)
    30     for(int i=0;i<n;i++) A[rev[i]]=a[i];
    31     for(int i=0;i<n;i++) a[i]=A[i];
    32     for(int m=2;m<=n;m<<=1){
    33         cp wn(cos(2.0*pi/m*flag),sin(2.0*pi/m*flag));
    34         for(int i=0;i<n;i+=m){
    35             cp w(1.0,0.0); int k=m>>1;
    36             for(int j=0;j<k;j++){
    37                 cp t=w*a[i+j+k], u=a[i+j];
    38                 a[i+j]=u+t;
    39                 a[i+j+k]=u-t;
    40                 w=w*wn;
    41             }
    42         }
    43     }
    44     if(flag==-1)for(int i=0;i<n;i++) a[i].r/=n;
    45 }
    46 void readin(cp *a){
    47     scanf("%s",str);
    48     int l=strlen(str);
    49     for(int i=0;i<l;i++) a[i].r=str[l-1-i]-'0';
    50 }
    51 int main(){
    52     scanf("%d",&len);
    53     len=len*2-1;
    54     readin(a); readin(b);
    55     brc(len);
    56     dft(a,len,1); dft(b,len,1);
    57     for(int i=0;i<len;i++) a[i]=a[i]*b[i];
    58     dft(a,len,-1);
    59     for(int i=0;i<len;i++) ans[i]=a[i].r+0.5;
    60     for(int i=0;i<len;i++) ans[i+1]+=ans[i]/10, ans[i]%=10;
    61     len++;
    62     while(!ans[len]&&len) len--;
    63     for(int i=len;i>=0;i--) printf("%d",ans[i]);
    64     return 0;
    65 }
    View Code

    2179: FFT快速傅立叶

    Time Limit: 10 Sec  Memory Limit: 259 MB
    Submit: 2567  Solved: 1308
    [Submit][Status][Discuss]

    Description

    给出两个n位10进制整数x和y,你需要计算x*y。

    Input

    第一行一个正整数n。 第二行描述一个位数为n的正整数x。 第三行描述一个位数为n的正整数y。

    Output

    输出一行,即x*y的结果。

    Sample Input

    1
    3
    4

    Sample Output

    12

    数据范围:
    n<=60000

    HINT

    Source

  • 相关阅读:
    框架Frameset 的JS 跳转 刷新 [转]
    Javascript的变量与delete操作符
    字符串替换方法的优劣
    Nutch介绍(译)
    权限系统—数据授权模型
    Apache Synapse介绍(译)
    java动态代理
    ASM简介
    maven使用技巧——构件搜索
    springSecurity源码分析——org.springframework.security.web.FilterInvocation类
  • 原文地址:https://www.cnblogs.com/Sunnie69/p/5573955.html
Copyright © 2011-2022 走看看