【HDU1402】【FFT】A * B Problem Plus
Problem Description
Calculate A * B.
Input
Each line will contain two integers A and B. Process to end of file.
Note: the length of each integer will not exceed 50000.
Note: the length of each integer will not exceed 50000.
Output
For each case, output A * B in one line.
Sample Input
1
2
1000
2
Sample Output
2
2000
Author
DOOM III
Recommend
DOOM III
【分析】
模板,不过我想说的是,这居然是06年的题目。。。太恐怖了。
1 /* 2 宋代苏轼 3 《临江仙·夜饮东坡醒复醉》 4 夜饮东坡醒复醉,归来仿佛三更。家童鼻息已雷鸣。敲门都不应,倚杖听江声。 5 长恨此身非我有,何时忘却营营。夜阑风静縠纹平。小舟从此逝,江海寄余生。 6 */ 7 #include <cstdio> 8 #include <cstring> 9 #include <algorithm> 10 #include <cmath> 11 #include <queue> 12 #include <vector> 13 #include <iostream> 14 #include <string> 15 #include <ctime> 16 #define LOCAL 17 const double Pi = acos(-1.0); 18 const int MAXN = 200000 + 10; 19 using namespace std; 20 typedef long long ll; 21 struct Num { 22 double a , b; 23 //构造函数 24 Num(double x = 0,double y = 0) {a = x; b = y;} 25 //复数的三种运算 26 Num operator + (const Num &c) {return Num(a + c.a, b + c.b);} 27 Num operator - (const Num &c) {return Num(a - c.a, b - c.b);} 28 Num operator * (const Num &c) {return Num(a * c.a - b * c.b, a * c.b + b * c.a);} 29 }x1[MAXN] , x2[MAXN]; 30 31 //注意loglen为log后的长度 32 void change(Num *t, int len, int loglen){ 33 //蝶形变换后的序列编号 34 for (int i = 0; i < len; i++){ 35 int x = i, k = 0; 36 for (int j = 0; j < loglen; j++, x >>= 1) k = (k << 1) | (x & 1); 37 if (k < i) swap(t[k], t[i]); 38 } 39 } 40 //基2-FFT 41 void FFT(Num *x, int len, int loglen){ 42 change(x, len, loglen); 43 int t = 1; 44 //t为长度 45 for (int i = 0; i < loglen; i++, (t <<= 1)){ 46 int l = 0, r = l + t; 47 while (l < len){ 48 //初始化 49 Num a, b, wo(cos(Pi / t), sin(Pi / t)), wn(1, 0); 50 for (int j = l; j < l + t; j++){ 51 a = x[j]; 52 b = x[j + t] * wn; 53 //蝶形计算 54 x[j] = a + b; 55 x[j + t] = a - b; 56 wn = wn * wo; 57 } 58 //注意是合并所以要走2t步 59 l = r + t; 60 r = l + t; 61 } 62 } 63 } 64 //离散傅里叶变换 65 void DFT(Num *x, int len, int loglen){ 66 int t = (1<<loglen); 67 for (int i = 0; i < loglen; i++){ 68 t >>= 1; 69 int l = 0, r = l + t; 70 while (l < len){ 71 Num a, b, wn(1, 0), wo(cos(Pi / t), -sin(Pi / t)); 72 for (int j = l; j < l + t; j++){ 73 a = x[j] + x[j + t]; 74 b = (x[j] - x[j + t]) * wn; 75 x[j] = a; 76 x[j + t] = b; 77 wn = wn * wo; 78 } 79 l = r + t; 80 r = l + t; 81 } 82 } 83 change(x, len, loglen); 84 for (int i= 0; i < len; i++) x[i].a /= len; 85 } 86 int solve(char *a, char *b){ 87 int len1, len2, len, loglen; 88 int t, over; 89 len1 = strlen(a) << 1; 90 len2 = strlen(b) << 1; 91 len = 1; 92 loglen = 0; 93 while (len < len1) len <<= 1, loglen++; 94 while (len < len2) len <<= 1, loglen++; 95 //处理len1 96 for (int i = 0; i < len; i++){ 97 if (a[i]) x1[i].a = a[i] - '0', x1[i].b = 0; 98 else x1[i].a = x1[i].b = 0; 99 } 100 for (int i = 0; i < len; i++){ 101 if (b[i]) x2[i].a = b[i] - '0', x2[i].b = 0; 102 else x2[i].a = x2[i].b = 0; 103 } 104 FFT(x1, len, loglen); 105 FFT(x2, len, loglen); 106 for (int i = 0; i < len; i++) x1[i] = x1[i] * x2[i]; 107 108 DFT(x1, len, loglen); 109 over = len = 0; 110 //转换成十进制的整数 111 for (int i = ((len1 + len2) / 2) - 2; i >= 0; i--){ 112 t = x1[i].a + over + 0.5; 113 a[len++] = t % 10; 114 over = t / 10; 115 } 116 while (over){ 117 a[len++] = over % 10; 118 over /= 10; 119 } 120 return len; 121 } 122 //输出 123 void print(char *str, int len){ 124 for(len--; len>=0 && !str[len];len--); 125 if(len < 0) putchar('0'); 126 else for(;len>=0;len--) putchar(str[len]+'0'); 127 printf("\n"); 128 } 129 char a[MAXN] , b[MAXN]; 130 131 int main() { 132 133 //char a[MAXN], b[MAXN]; 134 while(scanf("%s%s", a, b) != EOF) { 135 print(a, solve(a, b)); 136 memset(a, 0, sizeof(a)); 137 memset(b, 0, sizeof(b)); 138 } 139 //printf("%.10lf\n", Pi); 140 return 0; 141 }