Pentium.Labs

System全家桶:https://zhuanlan.zhihu.com/c_1238468913098731520

导航

hdu1402 FFT入门

参考这里:http://www.cnblogs.com/pdev/p/4354705.html

       http://www.cnblogs.com/pdev/p/4354629.html

 

题意:求大数乘法A*B

A和B位数很长。裸高精度时间复杂度是O(nm),会完蛋

 

不妨回忆下裸高精度的过程:

 

其实乘法的那一步很类似前面介绍过的多项式快速乘法诶(⊙▽⊙)

所以就可以用前述方法计算咯,时间复杂度O(nlogn)

 

我是这样理解的:

每个乘数都是都是一坨时域信号(一个大混合物),然后对乘数分别进行DFT(Discrete Fourier Transform)得到频域信号(一堆纯净物)。

然后对纯净物按类别分别相加,就得到了新信号(这里即乘法结果)对应的频域信号(一堆纯净物)

然后再来一次IDFT(Inverse DFT,逆变换)把频域再转成时域(一个大混合物,即真正的乘法结果)就好啦

 

总结一下本题的模式:

  读入向量x、y

  int len=1;  while(len < lx*2 || len < ly*2)len<<=1;    (lx、ly分别是向量x和y的长度)

  fft(x),fft(y)

  for i=0 to len-1    x[i]=x[i]*y[i]

  ifft(x)

  for(int i = 0; i < len; i++)  sum[i] = (int)(X[i].x+0.5);    变回整数

 

 

  1 #include  <stdio.h>
  2 #include  <string.h>
  3 #include  <iostream>
  4 #include  <algorithm>
  5 #include  <math.h>
  6 using namespace  std;
  7 const double PI = acos(-1.0);
  8 //复数结构体
  9 struct  Complex
 10 {
 11     double x,y;//实部和虚部  x+yi
 12     Complex(double _x = 0.0,double _y = 0.0)
 13     {
 14         x = _x;
 15         y = _y;
 16     }
 17     Complex operator -(const Complex &b)const
 18     {
 19         return  Complex(x-b.x,y-b.y);
 20     }
 21     Complex operator +(const Complex &b)const
 22     {
 23         return  Complex(x+b.x,y+b.y);
 24     }
 25     Complex operator *(const Complex &b)const
 26     {
 27         return  Complex(x*b.x-y*b.y,x*b.y+y*b.x);
 28     }
 29 };
 30 
 31 void change(Complex y[],int  len)
 32 {
 33     int  i,j,k;
 34     for(i = 1, j = len/2; i <len-1; i++)
 35     {
 36         if(i < j)swap(y[i],y[j]);
 37 //交换互为小标反转的元素,i<j保证交换一次
 38 //i做正常的+1,j左反转类型的+1,始终保持i和j是反转的
 39         k = len/2;
 40         while(j >= k)
 41         {
 42             j -= k;
 43             k /= 2;
 44         }
 45         if(j < k)j += k;
 46     }
 47 }
 48 
 49 
 50 void fft(Complex y[],int len,int  on)
 51 {
 52     change(y,len);
 53     for(int h = 2; h <= len; h <<= 1)
 54     {
 55         Complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
 56         for(int j = 0; j < len; j+=h)
 57         {
 58             Complex  w(1,0);
 59             for(int k = j; k < j+h/2; k++)
 60             {
 61                 Complex u = y[k];
 62                 Complex t = w*y[k+h/2];
 63                 y[k] = u+t;
 64                 y[k+h/2] = u-t;
 65                 w = w*wn;
 66             }
 67         }
 68     }
 69     if(on == -1)
 70         for(int i = 0; i < len; i++)
 71             y[i].x /= len;
 72 }
 73 
 74 
 75 const int MAXN = 200010;
 76 Complex  x1[MAXN],x2[MAXN];
 77 char  str1[MAXN/2],str2[MAXN/2];
 78 int  sum[MAXN];
 79 int main()
 80 {
 81     while(scanf("%s%s",str1,str2)==2)
 82     {
 83         int len1 = strlen(str1);
 84         int len2 = strlen(str2);
 85         int len = 1;
 86         while(len < len1*2 || len < len2*2)len<<=1;
 87         for(int i = 0; i < len1; i++)
 88             x1[i] =  Complex(str1[len1-1-i]-'0',0);
 89         for(int i = len1; i < len; i++)
 90             x1[i] =  Complex(0,0);
 91         for(int i = 0; i < len2; i++)
 92             x2[i] =  Complex(str2[len2-1-i]-'0',0);
 93         for(int i = len2; i < len; i++)
 94             x2[i] =  Complex(0,0);
 95 //x1[i]:x1对应的向量
 96 //例如1989就是(9,0)、(8,0)、(9,0)、(1,0)、(0,0)、...
 97 
 98 
 99         fft(x1,len,1);
100         fft(x2,len,1);
101 
102         for(int i = 0; i < len; i++)
103             x1[i] = x1[i]*x2[i];
104 
105         fft(x1,len,-1);
106 
107         for(int i = 0; i < len; i++)
108             sum[i] = (int)(x1[i].x+0.5);
109 /*
110         for(int i=0;i<len;i++)
111             cout<<sum[i]<<"  ";
112         cout<<endl;
113 */
114         for(int i = 0; i < len; i++)        //此时的sum存的东西还没进位,还得处理下
115         {
116             sum[i+1]+=sum[i]/10;
117             sum[i]%=10;
118         }
119         len = len1+len2-1;
120         while(sum[len] <= 0 && len > 0)len--;
121         for(int i = len; i >= 0; i--)
122             printf("%c",sum[i]+'0');
123         printf("\n");
124     }
125     return  0;
126 }
View Code

 

posted on 2015-04-27 21:47  Pentium.Labs  阅读(675)  评论(0编辑  收藏  举报



Pentium.Lab Since 1998