原题链接:蓝桥杯算法提高VIP-高精度乘法
解题思路:朴素的高精度乘法是一位一位存数的,而用于存储结果的int(我用的是short)数组中每一个元素显然能存储比9大得多的数,这就造成很多浪费。因而改为每次都进行k位数相乘,最终结果的每一个元素为k位数。这种做法不仅充分利用了数据范围,还大大减小时间复杂度的常数。
下面的代码实现了2位压位高精
注意事项:注释里有
参考代码:
//k位压位高精可以看成10^k进制,因此最终模数改为10^k
int add(short *num1,short *num2,int len1,int len2) {
int f=0; //进位标记。
int maxlen=max(len1,len2);
for(int i=0; i<maxlen; i++) {
int now=num1[i]+num2[i]+f;
res[i]=now%100;
f=now/100;
}
if(f) res[maxlen]=1;
return maxlen;
}
int mul(char *s1,char *s2) {
int len1=strlen(s1),len2=strlen(s2),res_len=0;
reverse(s1,s1+len1);
reverse(s2,s2+len2);
static short tmp[M+M]; //临时存储结果
//此处i每次加2,因此不再代表最后补0的位数,需要另一个计数器统计0的位数
for(int i=0,zero=0; i<len2; i+=2,zero++) {
int jw=0,cnt=0; //由于j每次加2,所以还要额外设置计数器cnt
if(zero!=0) tmp[zero-1]=0; //上一位清零
for(int j=0; j<len1; j+=2) {
//应防止最高位不够用
int fac1=(s2[i]-'0')+10*(max(s2[i+1],'0')-'0'),fac2=(s1[j]-'0')+10*(max(s1[j+1],'0')-'0');
int now=fac1*fac2+jw;
//tmp也是倒序,最后留i个0
tmp[zero+cnt++]=now%100;
jw=now/100;
}
//处理当前最高位
tmp[zero+cnt]+=jw;
res_len=add(res,tmp,res_len,zero+cnt+((tmp[zero+cnt]!=0)?1:0));
}
if(res[res_len]!=0) res_len++;
return res_len;
}
//输出注意:除最高位外,不足2位的补0,方法:printf("%02hd",res[i]);0.0分
1 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复