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