hdu1402(大数a*b&fft模板)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1402

 

题意: 给出两个长度1e5以内的大数a, b, 输出 a * b.

 

思路: fft模板

详情参见:  m.blog.csdn.net/f_zyj/article/details/76037583

       http://blog.csdn.net/sdj222555/article/details/9786527

      https://wenku.baidu.com/view/8bfb0bd476a20029bd642d85.html

可以将 a, b 看成两个多项式, 每个数位为一项, 每一位上的数字即为所在项的系数.所以直接fft即可.

 

代码:

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <math.h>
  4 #include <string.h>
  5 #include <stdio.h>
  6 using namespace std;
  7 
  8 const double PI = acos(-1.0);
  9 
 10 struct Complex{//复数结构体
 11     double x, y;//实部,虚部
 12     Complex(double _x = 0.0, double _y = 0.0){
 13         x = _x;
 14         y = _y;
 15     }
 16     Complex operator -(const Complex &b) const{
 17         return Complex(x - b.x, y - b.y);
 18     }
 19     Complex operator +(const Complex &b) const{
 20         return Complex(x + b.x, y + b.y);
 21     }
 22     Complex operator *(const Complex &b) const{
 23         return Complex(x * b.x - y * b.y, x * b.y + y * b.x);
 24     }
 25 };
 26 
 27 //进行FFT和IFFT反转变化
 28 //位置i和(i二进制反转后位置)互换
 29 void change(Complex y[], int len){//len必须为2的幂
 30     for(int i = 1, j = len / 2; i < len - 1; i++){
 31         if(i < j) swap(y[i], y[j]); //交换互为下标反转的元素,i<j保证只交换一次
 32         int k = len >> 1;
 33         while(j >= k){
 34             j -= k;
 35             k /= 2;
 36         }
 37         if(j < k) j += k;
 38     }
 39 }
 40 
 41 //做FFT,len必须为2的幂,on=1是DFT,on=-1是IDTF
 42 void fft(Complex y[], int len, int on){
 43     change(y, len);//调用反转置换
 44     for(int h = 2; h <= len; h <<= 1){
 45         Complex wn(cos(-on * 2 * PI / h), sin(-on * 2 * PI / h));
 46         for(int j = 0; j < len; j += h){
 47             Complex w(1, 0);//初始化螺旋因子
 48             for(int k = j; k < j + h / 2; k++){//配对
 49                 Complex u = y[k];
 50                 Complex t = w * y[k + h / 2];
 51                 y[k] = u + t;
 52                 y[k + h / 2] = u - t;
 53                 w = w * wn;//更新螺旋因子
 54             }
 55         }
 56     }
 57     if(on == -1){
 58         for(int i = 0; i < len; i++){
 59             y[i].x /= len;//IDTF
 60         }
 61     }
 62 }
 63 
 64 const int MAXN = 2e5 + 10;
 65 Complex x1[MAXN], x2[MAXN];
 66 char str1[MAXN >> 1], str2[MAXN >> 1];
 67 int sum[MAXN];
 68 
 69 int main(void){
 70     while(~scanf("%s%s", str1, str2)){
 71         int len1 = strlen(str1);
 72         int len2 = strlen(str2);
 73         int len = 1;
 74         while(len < len1 * 2 || len < len2 * 2) len <<= 1;
 75         //将str1,str2构造成两个多项式
 76         for(int i = 0; i < len1; i++){//倒存
 77             x1[i] = Complex(str1[len1 - i - 1] - '0', 0);
 78         }
 79         for(int i = len1; i < len; i++){
 80             x1[i] = Complex(0, 0);//不够的补0
 81         }
 82         for(int i = 0; i < len2; i++){
 83             x2[i] = Complex(str2[len2 - i - 1] - '0', 0);
 84         }
 85         for(int i = len2; i < len; i++){
 86             x2[i] = Complex(0, 0);
 87         }
 88         fft(x1, len, 1); //DFT(str1)
 89         fft(x2, len, 1); //DFT(str2);
 90         for(int i = 0; i < len; i++){
 91             x1[i] = x1[i] * x2[i];//点乘结果存入x1
 92         }
 93         fft(x1, len, -1);//IDFT(a*b)
 94         for(int i = 0; i < len; i++){
 95             sum[i] = (int)(x1[i].x + 0.5);//四舍五入
 96         }
 97         for(int i = 0; i < len; i++){
 98             sum[i + 1] += sum[i] / 10;
 99             sum[i] %= 10;
100         }
101         len = len1 + len2 - 1;//长度为len1和len2的两个数的乘积长度最大不超过len1+len2+1
102         while(sum[len] <= 0 && len > 0) len--;//去前导0
103         for(int i = len; i >= 0; i--){
104             printf("%d", sum[i]);
105         }
106         puts("");
107     }
108     return 0;
109 }
View Code

 

posted @ 2017-09-12 21:05  geloutingyu  阅读(474)  评论(0编辑  收藏  举报