大数乘法_字符串

题目

链接:http://lx.lanqiao.cn/problem.page?gpid=T364
 当两个比较大的整数相乘时,可能会出现数据溢出的情形。为避免溢出,可以采用字符串的方法来实现两个大数之间的乘法。具体来说,首先以字符串的形式输入两个整数,每个整数的长度不会超过8位,然后把它们相乘的结果存储在另一个字符串当中(长度不会超过16位),最后把这个字符串打印出来。例如,假设用户输入为:62773417和12345678,则输出结果为:774980393241726.

输入:
  62773417 12345678

输出:
  774980393241726

思路

参考了逐位相乘进位法。对乘数a、b,结果 c[j+i] = a[i] * b[j]

细节

1. 注意乘法结果的首位0
2. 注意乘数为0的情况

代码

#include <bits/stdc++.h>

#define MAX_N 30
using namespace std;

int main()
{
    string a,b;
    int multip[MAX_N];
    while (cin >> a >> b) {
		reverse(a.begin(), a.end());
		reverse(b.begin(), b.end());
		memset(multip, 0, sizeof(multip));

		if (atoi(a.c_str()) == 0 || atoi(b.c_str()) == 0) { puts("0"); continue;}

		for (int i = 0; i <= a.length()-1; i++) {
			for (int j = 0; j <= b.length()-1; j++) {
				multip[j+i] += (a[i]-'0') * (b[j]-'0');
			}
		}

		for (int n = 0; n < a.length()+b.length()-1; n++) {
			multip[n+1] += multip[n]/10;
			multip[n] = multip[n]%10;
		}

		int index = a.length()+b.length()-1;
		while (!multip[index]) {
			index--;
		}

		for (int n = index; n >= 0; n--) {
			cout << multip[n];
		}
		cout << endl;
    }
    return 0;
}

实测后,发现可以直接过蓝桥练习题中的高精度乘法运算的那题

更新: 按照紫书上的BigInteger类的实现方法,这种方法中的每个元素存储的是一个8位 的整数,只比每个元素存储1位数字时间复杂度快8倍,时间复杂度上并无质的飞跃,要再快就只好上FFT了。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
class BigInteger {
	static const int BASE = 100000000;
	static const int WIDTH = 8;
	vector<ll> s;

public:
	void printVect() {
		for (vector<ll>::iterator it = s.begin(); it != s.end(); it++) {
			cout << *it << " ";
		}
		cout << endl;
	}

	BigInteger(long long num = 0) { *this = num; }
	BigInteger operator = (long long num) {
		s.clear();
		do {
			s.push_back(num % BASE);
			num /= BASE;
		} while (num > 0);
		return *this;
	}

	BigInteger operator = (const string & str) {
		s.clear();
		long long x;
		int len = (str.length() - 1) / WIDTH + 1;
		for (int i = 0; i < len; i++) {
			int nd = str.length() - i*WIDTH;
			int strt = max(0, nd-WIDTH);
			sscanf(str.substr(strt, nd-strt).c_str(), "%lld", &x);
			s.push_back(x);
		}
		return *this;
	}

	BigInteger operator = (const char * str) {
		s.clear();
		long long x;
		int len = (strlen(str) - 1) / WIDTH + 1;
		for (int i = 0; i < len; i++) {
			int nd = strlen(str) - i*WIDTH;
			int strt = max(0, nd-WIDTH);
			x = (str[strt] - '0');
			for (int n = strt+1; n < nd; n++) {
				x = x*10 + (str[n] - '0');
			}
			s.push_back(x);
		}
		return *this;
	}

	void clean() {
		while(s.size() > 1 && !s[s.size()-1]) s.pop_back();
	}


	friend ostream& operator << (ostream &out, const BigInteger& x) {
		out << x.s.back();
		for (int i = x.s.size()-2; i >= 0; i--) {
			char buf[20];
			sprintf(buf, "%08lld", x.s[i]);
			for (unsigned int j = 0; j < strlen(buf); j++) out << buf[j];
		}
		return out;
	}

	void putout_cstr() {
		printf("%lld", this->s.back());
		for (int i = this->s.size()-2; i >= 0; i--) {
			char buf[20];
			sprintf(buf, "%08lld", this->s[i]);
			for (unsigned int j = 0; j < strlen(buf); j++) putchar(buf[j]);
		}
	}

	friend  istream & operator >> (istream & in, BigInteger & x) {
		string s;
		if (! (in>>s) ) return in;
		x = s;
		return in;
	}

	BigInteger operator + (const BigInteger & b) {
		BigInteger c;
		c.s.clear();
		for (int i = 0, g = 0; ; i++) {
			if (g == 0 && i >= s.size() && i >= b.s.size()) break;
			long long x = g;
			if (i < s.size()) x += s[i];
			if (i < b.s.size()) x += b.s[i];
			c.s.push_back(x % BASE);
			g = x / BASE;
		}
		return c;
	}

	BigInteger operator * (const BigInteger & b) {
		BigInteger c;
		c.s.clear();
		c.s.resize(s.size() + b.s.size(), 0);

		for (unsigned int i = 0; i <= s.size()-1; i++) {
			for (unsigned int j = 0; j <= b.s.size()-1; j++) {
				c.s[j+i] += s[i] * b.s[j];
			}
		}

		for(int k = 0; k < c.s.size(); k++){
		  c.s[k+1] += c.s[k] / BASE;
		  c.s[k] %= BASE;
		}

		c.clean();

		return c;
	}

};

//string a,b;

#define MAX_N 100010
int main() {

//	freopen("input1.txt", "r", stdin);
//	freopen("input1.out", "w+", stdout);
//	while (cin >> a >> b) {
	char a[MAX_N], b[MAX_N];
	while (~scanf("%s %s", a, b) ) {
		BigInteger bigA,bigB, bigC;
		bigA = a; bigB = b;
//		cout << "a: " << bigA << " b: " << bigB << endl;
		bigC = bigA * bigB;
		bigC.putout_cstr();	printf("\n");
//		cout << bigC << endl;
	}
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值