hdu1402(大數a*b&fft模板)
阿新 • • 發佈:2017-09-12
net display img 初始化 stdio.h 位置 scanf ios https
題目鏈接: http://acm.hdu.edu.cn/showproblem.php?pid=1402
題意: 給出兩個長度1e5以內的大數a, b, 輸出 a * b.
思路: fft模板
詳情參見: http://blog.csdn.net/sdj222555/article/details/9786527
https://wenku.baidu.com/view/8bfb0bd476a20029bd642d85.html
可以將 a, b 看成兩個多項式, 每個數位為一項, 每一位上的數字即為所在項的系數.所以直接fft即可.
代碼:
1 #include <iostream> 2View Code#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 }
hdu1402(大數a*b&fft模板)