题目就是求一个大数的乘法
这里数字的位数有50000的长度,按平时的乘法方式计算,每一位相乘是要n^2的复杂度的,这肯定不行
我们可以将每一位分解后作为系数,如153 = 1*x^2 + 5*x^1 + 3*x^0 (在这里x可以理解成10)
那么两个数字相乘就相当于系数相乘后得到新的系数组合
如153 * 4987 = <3,5,1> * <7,8,9,4>
这相当于卷积的计算,最快的方式就是fft,nlgn的复杂度就能求解,求解得到后再把每一位大于10往前赋值就行了
1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <algorithm> 5 #include <math.h> 6 7 using namespace std; 8 const double PI = acos(-1.0); 9 10 struct complex{ 11 double r , i; 12 complex(double r=0 , double i=0):r(r),i(i){} 13 complex operator+(const complex &a) const{ 14 return complex(r+a.r , i+a.i); 15 } 16 complex operator-(const complex &a) const{ 17 return complex(r-a.r , i-a.i); 18 } 19 complex operator*(const complex &a) const{ 20 return complex(r*a.r-i*a.i , r*a.i+i*a.r); 21 } 22 }; 23 24 void change(complex y[] , int len) 25 { 26 int i,j,k; 27 for(i=1 , j=len/2 ; i<len-1 ; i++){ 28 if(i<j) swap(y[i],y[j]); 29 k = len/2; 30 while(j>=k){ 31 j-=k; 32 k/=2; 33 } 34 if(j<k) j+=k; 35 } 36 } 37 38 void fft(complex y[] , int len , int on) 39 { 40 change(y , len); 41 for(int i=2 ; i<=len ; i<<=1){ 42 complex wn(cos(-on*2*PI/i) , sin(-on*2*PI/i)); 43 for(int j=0 ; j<len ; j+=i){ 44 complex w(1,0); 45 for(int k=j ; k<j+i/2 ; k++){ 46 complex u = y[k]; 47 complex t = w*y[k+i/2]; 48 y[k] = u+t; 49 y[k+i/2] = u-t; 50 w = w*wn; 51 } 52 } 53 } 54 if(on==-1) 55 for(int i=0 ; i<len ; i++) 56 y[i].r /= len; 57 58 } 59 60 const int MAXN = 200010; 61 complex x1[MAXN] , x2[MAXN]; 62 char str1[MAXN] , str2[MAXN]; 63 int sum[MAXN]; 64 65 int main() 66 { 67 while(~scanf("%s%s" , str1 , str2)){ 68 int len1 = strlen(str1) , len2 = strlen(str2); 69 int len = 1; 70 //fft的计算,由于是倍增的,需要保证是2^k次方,且要大于最后得到的结果的总位数 71 while(len<len1*2 || len<len2*2) len<<=1; 72 for(int i=0 ; i<len1 ; i++) 73 x1[i] = complex(str1[len1-1-i]-‘0‘ , 0); 74 for(int i=len1 ; i<len ; i++) 75 x1[i] = complex(0 , 0); 76 for(int i=0 ; i<len2 ; i++) 77 x2[i] = complex(str2[len2-1-i]-‘0‘ , 0); 78 for(int i=len2 ; i<len ; i++) 79 x2[i] = complex(0 , 0); 80 //将当前的组合数的系数值修改成复数坐标系的点值o(nlgn) 81 fft(x1 , len , 1); 82 fft(x2 , len , 1); 83 //点值可以o(n)的时间内进行计算 84 for(int i=0 ; i<len ; i++) 85 x1[i] = x1[i]*x2[i]; 86 //将点值重新通过逆过程(又叫dft)转化为系数值 87 fft(x1 , len , -1); 88 89 memset(sum , 0 , sizeof(sum)); 90 for(int i=0 ; i<len ; i++) sum[i] = (int)(x1[i].r+0.5); 91 for(int i=0 ; i<len ; i++){ 92 sum[i+1] += sum[i]/10; 93 sum[i] = sum[i]%10; 94 } 95 int ansl = len1+len2-1; 96 while(sum[ansl]==0 && ansl>0) ansl--; 97 for(int i=ansl ; i>=0 ; i--) printf("%c" , sum[i]+‘0‘); 98 printf("\n"); 99 } 100 return 0; 101 }
时间: 2024-11-05 22:47:56