https://www.luogu.org/problemnew/show/P1303(题目传送门)
看到数据范围,显然要用高精度算法(乘法)。
首先用字符串读下这最多达10^2000的数,并判断符号。若为负号,我们只用把它的数值存到数组里就行了;否则,就将它所有元素都存到数组里。(注意,若两数异号,则需输出一个负号。)
之后就到了高精度乘法的核心:仍然用竖式的思想,通过几个例子发现,a[i]与b[i]的乘积都会被加到用与存储结果的输出c中的c[i+j-1]中。而对于c[i+j-1],我们只需要考虑a[i]*b[i]的值与它原来的值(进位与上次关于它的乘法)就好。若c[i+j-1]大于10,就让它的下一位c[i+j]+=c[i+j-1](即进位),并保留c[i+j-1]的个位。如此下来,就得到了结果——最多为i+j位的数,之后就开始判断(首位0)并输出了。
上代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 int a[2001],b[2001],c[4002]; 6 char s1[2002],s2[2002]; 7 int main() 8 { 9 10 cin>>s1>>s2; 11 bool fu=0; 12 int j1=strlen(s1),j2=strlen(s2); 13 if(s1[0]=='-') 14 { 15 --j1; 16 fu=!fu; 17 } 18 if(s2[0]=='-') 19 { 20 --j2; 21 fu=!fu; 22 } 23 if(fu) cout<<'-'; 24 for(int i=1;i<=j1;++i) 25 a[i]=s1[strlen(s1)-i]-'0'; 26 for(int i=1;i<=j2;++i) 27 b[i]=s2[strlen(s2)-i]-'0'; 28 for(int i=1;i<=j1;++i) 29 { 30 for(int j=1;j<=j2;++j) 31 { 32 c[i+j-1]+=a[i]*b[j]; 33 if(c[i+j-1]>=10) 34 { 35 c[i+j]+=c[i+j-1]/10; 36 c[i+j-1]%=10; 37 } 38 } 39 } 40 int k=j1+j2; 41 while(!c[k]&&k>1) k--; 42 for(;k>=1;k--) 43 cout<<c[k]; 44 return 0; 45 }
几点注意:
1、a数组和b数组倒序存的是输入数的大小,因此应将s1,s2的每一位-‘0’再存入数组(取字符与‘0’的相对位置,即字符代表意义上的数值的大小,而不是ASCLL码的大小)
2、(如果c全0的话)注意保留c最后一位0输出。(防止积为0但是没输出的情况)。