hdu 1402 A * B Problem Plus

此处介绍另一种方法来解决这题,也就是FFT(快速傅里叶变换)

 

如果是乘法,位数为n和位数为m的相乘,需要n*m次的乘法运算。

 

FFT在数字信号处理学过,但是第一次用来做这类题目,神奇啊。

 

乘法其实就是做线性卷积。

 

用DFT得方法可以求循环卷积,但是当循环卷积长度LN+M-1,就可以做线性卷积了。

 

使用FFT将两个数列转换成傅里叶域,在这的乘积就是时域的卷积。

 

 

 

给几个学习的链接吧:

 

http://wenku.baidu.com/view/8bfb0bd476a20029bd642d85.html  (这主要看那个FFT的流程图

 

http://wlsyzx.yzu.edu.cn/kcwz/szxhcl/kechenneirong/jiaoan/jiaoan3.htm   这有DFT的原理。

  1 #include<iostream>

  2 #include<stdio.h>

  3 #include<algorithm>

  4 #include<iomanip>

  5 #include<cmath>

  6 #include<cstring>

  7 #include<vector>

  8 #define ll __int64

  9 #define pi acos(-1.0)

 10 using namespace std;

 11 const int MAX = 200002;

 12 //复数结构体

 13 struct complex{

 14     double r,i;

 15     complex(double R=0,double I=0){

 16         r=R;i=I;

 17     }

 18     complex operator+(const complex &a){

 19         return complex(r+a.r,i+a.i);

 20     }

 21     complex operator-(const complex &a){

 22         return complex(r-a.r,i-a.i);

 23     }

 24     complex operator*(const complex &a){

 25         return complex(r*a.r-i*a.i,r*a.i+i*a.r);

 26     }

 27 };

 28 /*

 29  *进行FFT和IFFT前的反转变换

 30  *位置i和i的二进制反转后位置互换,(如001反转后就是100)

 31  *len必须去2的幂

 32  */

 33 void change(complex x[],int len){

 34     int i,j,k;

 35     for(i = 1, j = len/2; i <len-1; i++){

 36         if (i < j) swap(x[i],x[j]);

 37         //交换互为小标反转的元素,i<j保证交换一次

 38         //i做正常的+1,j做反转类型的+1,始终i和j是反转的

 39         k = len/2;

 40         while (j >= k){

 41             j -= k;

 42             k /= 2;

 43         }

 44         if (j < k) j += k;

 45     }

 46 }

 47 /*

 48  *做FFT

 49  *len必须为2^n形式,不足则补0

 50  *on=1时是DFT,on=-1时是IDFT

 51  */

 52 void fft (complex x[],int len,int on){

 53     change(x,len);

 54     for (int i=2;i<=len;i<<=1){

 55         complex wn(cos(-on*2*pi/i),sin(-on*2*pi/i));

 56         for (int j=0;j<len;j+=i){

 57             complex w(1,0);

 58             for (int k=j;k<j+i/2;k++){

 59                 complex u = x[k];

 60                 complex t = w*x[k+i/2];

 61                 x[k] = u+t;

 62                 x[k+i/2] = u-t;

 63                 w = w*wn;

 64             }

 65         }

 66     }

 67     if (on == -1){

 68         for (int i=0;i<len;i++){

 69             x[i].r /= len;

 70         }

 71     }

 72 }

 73 complex x1[MAX],x2[MAX];

 74 char str1[MAX/2],str2[MAX/2];

 75 ll num[MAX],sum[MAX];

 76 int main()

 77 {

 78     int i,j,k,len1,len2,len;

 79     while(scanf("%s%s",&str1,&str2)!=EOF){

 80         len1 = strlen(str1);

 81         len2 = strlen(str2);

 82         len = 1;

 83         while (len < 2*len1 || len < 2*len2) len<<=1;

 84         for (i=0;i<len1;i++){

 85             x1[i] = complex(str1[len1-1-i]-'0',0);

 86         }

 87         for (i=len1;i<len;i++){

 88             x1[i] = complex(0,0);

 89         }

 90         for (i=0;i<len2;i++){

 91             x2[i] = complex(str2[len2-1-i]-'0',0);

 92         }

 93         for (i=len2;i<len;i++){

 94             x2[i] = complex(0,0);

 95         }

 96         fft(x1,len,1);

 97         fft(x2,len,1);

 98         for (i=0;i<len;i++){

 99             x1[i] = x1[i]*x2[i];

100         }

101         fft(x1,len,-1);

102         for (i=0;i<len;i++){

103             sum[i] = (int)(x1[i].r+0.5);

104         }

105         for (i=0;i<len;i++){

106             sum[i+1]+=sum[i]/10;

107             sum[i]%=10;

108         }

109         len = len1+len2-1;

110         while (sum[len]<=0 && len>0) len--;

111         for (i=len;i>=0;i--){

112             printf("%c",sum[i]+'0');

113         }

114         printf("\n");

115     }

116     return 0;

117 }
View Code

 

 

你可能感兴趣的:(HDU)