高效万进制——蓝桥杯|HDOJ 1002 大数加法——30行代码AC

浅谈进制思想:

日常生活中我们习惯用十进制去运算;
为了方便电脑识别开发出了二进制,又因为2^3=8 , 2^4=16,因此应运而生了八进制与16进制。
世上本没有路,走的人多了,也便成了路,那么既然二进制可以衍生出8,16进制,为什么十进制不可以呢。
因此聪明的人们开发出了万进制,也就是10^4=10000 模仿二进制与十六进制的运算。渐渐的,我们发现万进制在进行大数运算方面有着无可比拟的优势。
如:662343889 * 5 = 3311719445
那么如果用万进制计算:可以设一个数组a[3]; a[2] = 3889 ; a[1] = 6234 ; a[0] = 6 ;
第一步:a[2] * 5 = 19445 ; 19445 %10000 = 1余9445 9445留下,1进位;
第二步:a[1] * 5 = 31170 ; 31170 %10000 = 3余1170 1170留下,加上进位的1为1171(终值),3进位;
第三步:a[0] * 5 = 30 ; 30+3(进位)为终值。
按顺序输出得:3311719945 ;仅仅三步我们便得出了最后结果,如果用十进制呢?每位相加,对于本例,至少要十步吧。效率快了3倍不止。

注意点:

本题 严格 模拟手算。(见11行-19行代码)
1、本题用万能头文件代替#include<iostream>#include<iomanip>
传送门→万能头文件
2、万进制逢万进一,效率极高,日后做ACM也是非常优秀的代码。
3、用cin输入char型数组,a[strlen(a)]的值为空, 一定要补0!见第九行代码。(笔者被坑的很惨)
4、最后输出时,第一要过滤值为0的数,第二要过滤第一个值不为0的数。(见21-28行代码)
如:0000 0123 2345 。 这个数的0000不能输出。且0123要变为123
5、26行的作用是:让形如:1234   567 2345 的数,变为:1234 0567 2345

代码:

#include<bits/stdc++.h>
using namespace std;
int main() {
	char a1[100], a2[100]; memset(a1,'0',sizeof(a1)); memset(a2,'0',sizeof(a2));
	int b1[25];	memset(b1, 0, sizeof(b1));			//int型长度是char型的四分之一
	cin >> a1 >> a2;
	reverse(a1,a1+strlen(a1));  reverse(a2,a2+strlen(a2)); 	//这里要反转两次
	reverse(a1,a1+100);	reverse(a2,a2+100);
	a1[strlen(a1)] = '0';  a2[strlen(a2)] = '0';	//这里需要置0,否则是空。
	int places = 0, carry;
	for(int i = 99; i >= 0; i -= 4) {
		carry = 0;
		b1[places] += ((a1[i-3]-'0')*1000+(a1[i-2]-'0')*100+(a1[i-1]-'0')*10+(a1[i]-'0')+
		(a2[i-3]-'0')*1000+(a2[i-2]-'0')*100+(a2[i-1]-'0')*10+(a2[i]-'0'));
		carry = b1[places]/10000;
		b1[places]%=10000; 
		places++;						//下一位 
		if(carry > 0) b1[places]++; 	//进位 
	}
	bool flag1 = false, flag2 = false;
	for(int i = places; i >= 0; i--) {
		if(!flag1 && b1[i] == 0) continue;	//忽略前导0 
		else {
			flag1 = !flag1; 
			if(!flag2) { flag2 = !flag2; cout << b1[i]; }	 
			else cout << setw(4) << setfill('0') << b1[i];		//填充0
		}
	}
	return 0;
}
发布了73 篇原创文章 · 获赞 61 · 访问量 4759

猜你喜欢

转载自blog.csdn.net/weixin_43899069/article/details/104563632