POJ 2737_大整数除法

总时间限制:
1000ms
内存限制:
65536kB
描述

求两个大的正整数相除的商。

输入
第1行是被除数,第2行是除数。每个数均不超过100位。
输出
一行,相应的商的整数部分
样例输入
2376
24
样例输出
99

把除法转换成大整数减法,商是几就是能减多少次除数,但是一直减太慢了,会超时(比如1000000000000000000…0/10),所以每次减掉被除数的 1 0 n 10^n 10n倍,直到不能减了再缩小10倍。

如 120 / 2,先把20变为 2 ∗ 1 0 2 = 200 2 * 10^2 = 200 2102=200(位数和被除数一样多),发现120不够减,于是缩小10倍,变为20,发现能减6次,于是答案是60.

并且在扩大10的n次幂的时候不用做乘法,在低位补0就好了,缩小倍数的时候也是一样,去掉低位0.
AC代码如下:

#include
#include
using namespace std;
struct BigInt {
	int bsize;
	int digit[10000];
	void init() {
		bsize = 0;
		for (int i = 0; i < 10000; ++i)digit[i] = 0;
	}
	void set(char str[]) {
		init();
		int L = strlen(str);
		for (int i = L - 1, c = 1, t = 0, j = 0; i >= 0; --i) {
			int x = str[i] - '0';
			t += x * c;
			c *= 10;
			++j;
			if (j == 1 || i == 0) {
				digit[bsize++] = t;
				t = 0;
				c = 1;
				j = 0;
			}
		}
	}
	void output() {
		if (bsize == 0) { printf("0\n"); return; }
		for (int i = bsize - 1; i >= 0; --i) {
			if (i == bsize - 1) printf("%d", digit[i]);
			else
			{
				printf("%01d", digit[i]);
			}
		}
		printf("\n");
	}

	//向右移x位
	void move(int x) {
		if (x == 0)return;
		for (int i = bsize - 1; i >= 0; --i) {
			digit[i + x] = digit[i];
		}
		for (int i = 0; i < x; ++i) {
			digit[i] = 0;
		}
		bsize += x;
	}
	//向左移x位
	void moveL(int x) {
		if (x == 0)return;
		for (int i = 0; i <= bsize - x; ++i) {
			digit[i] = digit[i + x];
		}
		for (int i = bsize - x + 1; i < bsize - 1; ++i) {
			digit[i] = 0;
		}
		bsize -= x;
	}
	int isBigger(BigInt A) {
		bool f = false;
		if (bsize > A.bsize)return 1;
		if (bsize < A.bsize)return -1;
		for (int i = bsize - 1; i >= 0; --i) {
			if (digit[i] > A.digit[i]) f = true;
			else if (digit[i] < A.digit[i]) {
				if (!f) return -1;
			}
		}
		return f ? 1 : 0;
	}

	//默认被减数大于等于减数

	BigInt operator - (const BigInt &A)const {
		BigInt ret;
		ret.init();
		bool isBor = false;
		for (int i = 0; i < bsize || i < A.bsize; ++i) {
			int tmp = isBor ? digit[i] - A.digit[i] - 1 : digit[i] - A.digit[i];
			if (tmp < 0) {
				isBor = true;
				tmp += 10;
			}
			else
			{
				isBor = false;
			}
			ret.digit[ret.bsize++] = tmp;
		}
		bool f = false;
		for (int i = ret.bsize - 1; i >= 0; --i) {
			if (ret.digit[i] != 0) {
				f = true;
				break;
			}
			if (ret.digit[i] == 0 && !f) {
				ret.bsize--;
			}
		}
		return ret;

	}


};



int main()
{
	char str1[210];
	char str2[210];
	while (~scanf("%s%s", str1, str2)) {
		if (strcmp(str2, "0") == 0) {
			printf("0\n");
			continue;
		}
		BigInt B1, B2;
		B1.set(str1);
		B2.set(str2);
		int ans[155];
		memset(ans, 0, sizeof(ans));
		BigInt ret;
		ret.init();
		if (B1.isBigger(B2) == -1) {
			printf("0\n");
			continue;
		}
		if (B1.isBigger(B2) == 0) {
			printf("1\n");
			continue;
		}
		ret = B1 - B2;
		ans[0] ++;
		int nTimes = ret.bsize - B2.bsize;
		if (nTimes < 0) {
			goto OutputResult;
		}
		else if (nTimes > 0)
		{
			B2.move(nTimes);
		}
		for (int j = 0; j <= nTimes; ++j) {
			int nTmp;
			while (ret.isBigger(B2) > 0)
			{
				ret = ret - B2;
				ans[nTimes - j]++;
			}
			if (ret.isBigger(B2) == 0)
			{
				ret = ret - B2;
				ans[nTimes  - j]++;
				break;
			}
			B2.moveL(1);
		}
	OutputResult:
		for (int i = 0; i < 150; ++i) {
			if (ans[i] >= 10) {
				ans[i + 1] += ans[i] / 10;
				ans[i] %= 10;
			}
		}
		bool f = false;
		for (int i = 150; i >= 0; --i) {
			if (f)printf("%d", ans[i]);
			else if (ans[i]) {
				printf("%d", ans[i]);
				f = true;
			}
		}
		printf("\n");


	}
	system("pause");
	return 0;
}

不太好的是使用了goto语句。。

你可能感兴趣的:(POJ)