60分,错一个超时一个
查看原帖
60分,错一个超时一个
749028
QAQ5楼主2024/7/26 15:13
#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <string>
using namespace std;
typedef unsigned long L;
// 是否开启调试模式
//#define DEBUG

// 只用到等于和加
class bigNum {
	unsigned char* aPosNums;
	bool isOne;
public:
	L numLen, saveSize;
	bigNum(string str, L size) {
		isOne = false;
#ifdef DEBUG
		cout << "创建数字,以文字内容:" << str << ",长度为:" << str.length() << ",存储大小为:" << size << endl;
#endif // DEBUG
		aPosNums = new unsigned char[size];
#ifdef DEBUG
		puts("大小分配完毕");
#endif // DEBUG
		saveSize = size;
		L i;
		// 输入的文字分位存在数字组中,遍历法,一字占一数
		for (i = 0/*长整可以让数字到四十亿长*/; i < str.length()/*为什么是函数不是属性*/; i++) {
			aPosNums[i] = str[i] - '0';
		}
		numLen = i;
#ifdef DEBUG
		puts("创建完毕,结果内容检测:");
		for (i = 0; i < numLen; i++) {
			cout << aPosNums[i] << ' ';
		}
		putchar('\n');
#endif // DEBUG
	}
	// 下面三运算添加调试显示会让结果不好看,除非在另一个控制台显示,不会
	// 只有文字才能用这么大数
	string toString() {
		string result;
		char a[] = "a";
		for (L i = 0; i < numLen; i++) {
			a[0] = aPosNums[i] + '0';
			result.append(a);
		}
		return result;
	}
	void operator=(bigNum b) {
		for (L i = 0; i < b.numLen; i++) {
			aPosNums[i] = b.aPosNums[i];
		}
		numLen = b.numLen;
		if (b.isOne)
			delete b.aPosNums;
	}
	bigNum operator+(bigNum addition) {
		// 忘了得复制一个分开
		bigNum result(toString(), saveSize);
		result.isOne = true;
		// 复合太难了,还是分支容易,最大的情况放最外面分
		// 三种长度情况,自己更长,加数更长,相等的情况最少见故而放最后
		if (result.numLen > addition.numLen) {
			// 自己更大,以加数长度为相加遍历终点,从尾部开始计算
			L i, i2;// 循环外部需要使用,声明在外面
			for (i = addition.numLen - 1, i2 = result.numLen - 1; i > 0/*不可小于零,最后一次额外处理*/; i--, i2--) {
				result.aPosNums[i2] += addition.aPosNums[i];
				// 相加后溢出处理
				if (result.aPosNums[i2] > 9) {
					// 只能溢个1
					result.aPosNums[i2] -= 10;
					result.aPosNums[i2 + 1]++;
				}
			}
			if (result.aPosNums[i2] > 9) {
				result.aPosNums -= 10;
				// 到头了,进一位
				if (i2 == 0) {
					for (i = result.numLen; i > 0; i--) {
						result.aPosNums[i] = result.aPosNums[i - 1];
					}
					result.aPosNums[0] = 1;
					result.numLen++;
				}// 否则继续往左加
				else {
					do {
						i2--;
						result.aPosNums[i2]++;
						if (result.aPosNums[i2] > 9) {
							result.aPosNums[i2] -= 10;
							result.aPosNums[i2 - 1]++;
						}
					} while (i2 != 0);
					// 此处用跳转方便还能减少复制粘贴,可是怎得。复制粘贴完全没有必要?
					if (result.aPosNums[0] > 9) {
						for (i = result.numLen; i > 0; i--) {
							result.aPosNums[i] = result.aPosNums[i - 1];
						}
						result.aPosNums[0] = 1;
						result.numLen++;
					}
				}
			}
		}
		else if (result.numLen < addition.numLen) {
			// 才敲了一种情况,还有两种
			// 先位移,准备先将加数多出来的部分加入前面
			L i, gap = addition.numLen - result.numLen;
			for (i = result.numLen - 1; i > 0; i--) {
				result.aPosNums[i + gap] = result.aPosNums[i];
			}
			// 加入前数
			result.aPosNums[i + gap] = result.aPosNums[i];
			for (i = 0; i < result.numLen; i++) {
				result.aPosNums[i] = addition.aPosNums[i];
			}
			// 后部分相加,除了原来的最高位
			for (i = addition.numLen - 1; i > result.numLen; i--) {
				result.aPosNums[i] += addition.aPosNums[i];
				if (result.aPosNums[i] > 9) {
					result.aPosNums[i] -= 10;
					result.aPosNums[i - 1]++;
				}
			}
			// 处理溢出传数进位
			result.aPosNums[i] += addition.aPosNums[i];
			while (i != 0 && result.aPosNums[i] > 9) {
				result.aPosNums[i--] -= 10;
				result.aPosNums[i]++;
			}
			// 虽然本来那次位移如果之前能推测出来一次就可以,但这种进位少
			if (result.aPosNums[0] > 9) {
				// 到底了还要进一位,整体右移让出一位用来进
				for (i = addition.numLen; i > 0; i--) {
					result.aPosNums[i] = result.aPosNums[i - 1];
				}
				result.aPosNums[0] = 1;
				result.numLen = addition.numLen + 1;
			}
			else
				result.numLen = addition.numLen;
		}//否则只能是相等,最简单的?
		else {
			L i;
			// 除最高位相加
			for (i = result.numLen - 1; i > 0; i--) {
				result.aPosNums[i] += addition.aPosNums[i];
				if (result.aPosNums[i] > 9) {
					result.aPosNums[i] -= 10;
					result.aPosNums[i - 1]++;
				}
			}
			// 最高位特殊处理
			result.aPosNums[i] += addition.aPosNums[i];
			// 最高位进位,右移补一
			if (result.aPosNums[i] > 9) {
				result.aPosNums[i] -= 10;
				for (i = result.numLen; i > 0; i--) {
					result.aPosNums[i] = result.aPosNums[i - 1];
				}
				result.aPosNums[0] = 1;
				result.numLen++;
			}
		}
		return result;
	}
};

int main() {
	string num1, num2;
	cin >> num1 >> num2;
	bigNum n1(num1, 40), n2(num2, 40);
	cout << (n1 + n2).toString();
}
2024/7/26 15:13
加载中...