目录
高精度加法
【题目传送门】
信息学奥赛一本通(C++版)在线评测系统http://ybt.ssoier.cn:8088/problem_show.php?pid=1168A+B Problem(高精) - 洛谷
https://www.luogu.com.cn/problem/P1601
【算法】
先说最简单的高精度加法,很简单,模拟竖式就行了
例如:123 + 968:
1 2 3
+ 9 6 8
--------1----
1 0 9 1
现将两个数每一位都相加,最后处理进位(高位加上本位除以 10,本位模 10)
注意,需要从低位到高位相加,因此需要将两个数倒过来,然后从 1 遍历到更大的长度(可以开全局数组,这样初值就都是零,位数小的数高位就都是 0,和位数大的数的高位加起来不变),这样输出就需要倒序输出
可以用一个变量 x 表示上一位的进位,每次 x 变成本次的数除以 10,然后每次答案加上 x,再模 10
最后需要处理一下最高位的进位,也就是判断最终 x 有没有值,如果有,就输出 x
具体请看下方代码
【代码】
(代码中,输入两个数分别为字符串 s,s1,s 和 s1 转换成数后为 a 数组和 b 数组,答案存放在 c 数组中)
#include <iostream>
#include <algorithm>
#include <string>
#define N 205
using namespace std;
string s, s1;
int a[N], b[N], c[N], x;
int main() {
cin >> s >> s1;
for(int i = 0; i < s.size(); ++i)
a[s.size() - i] = s[i] - 48;
for(int i = 0; i < s1.size(); ++i)
b[s1.size() - i] = s1[i] - 48;
int l = max(s.size(), s1.size());
for(int i = 1; i <= l; ++i) {
c[i] = (a[i] + b[i] + x) % 10;
x = (a[i] + b[i] + x) / 10;
}
if(x)
cout << x;
for(int i = l; i > 0; --i)
cout << c[i];
cout << endl;
return 0;
}
高精度减法
【题目传送门】
信息学奥赛一本通(C++版)在线评测系统http://ybt.ssoier.cn:8088/problem_show.php?pid=1169高精度减法 - 洛谷
https://www.luogu.com.cn/problem/P2142
【算法】
也很简单,模拟竖式
例如:81 - 79:
、
8 1
- 7 9
----------
2
注意,这次要判断负数了,就看如果第二个大,就输出一个 '-' ,然后调换两数
也是逆序存储,然后从前往后遍历,遍历到大数的长度,大数减小数
如果发现不够减,则大数的上一位减一,本位减后加 10(借位)
注意,最后要去掉前导 0
具体请看下方代码
【代码】
(代码中,输入两个数分别为字符串 s,s1,s 和 s1 转换成数后 a 数组存储大数, b 数组存储小数,答案存放在 a 数组中,f 表示是否答案会是负数)
#include <iostream>
#include <string>
#define N 205
using namespace std;
string s, s1;
int a[N], b[N];
bool f;
int main() {
cin >> s >> s1;
if(s.size() < s1.size())
f = 1;
else if(s.size() == s1.size())
for(int i = 0; i < s.size(); ++i)
if(s[i] < s1[i]) {
f = 1;
break;
}
if(f) {
cout << "-";
swap(s, s1);
}
for(int i = 0; i < s.size(); ++i)
a[s.size() - i] = s[i] - 48;
for(int i = 0; i < s1.size(); ++i)
b[s1.size() - i] = s1[i] - 48;
int l = max(s.size(), s1.size());
for(int i = 1; i <= l; ++i) {
a[i] -= b[i];
if(a[i] < 0) {
--a[i + 1];
a[i] += 10;
}
}
while(!a[l] && l > 1)
--l;
for(int i = l; i > 0; --i)
cout << a[i];
cout << endl;
return 0;
}
高精度乘法
【题目传送门】
信息学奥赛一本通(C++版)在线评测系统http://ybt.ssoier.cn:8088/problem_show.php?pid=1307A*B Problem - 洛谷
https://www.luogu.com.cn/problem/P1303
【算法】
模拟竖式
例如:13 * 72:
1 3
× 7 2
-----------
2 6
9 1
----------
9 3 6
首先,也一定是逆序存储
观察后发现第 i 为和第 j 位相乘后被加到了第 (i + j - 1) 位(逆序存储后)
有了这个规律,我们就可以将每种位数的两两组合枚举出来,然后第 (i + j - 1) 位存储 i 和 j 位相乘的结果
注意要处理进位,而进到最高位的时候还需要向更高位 (i + j) 位进位(i + j - 1 + 1 等于 i + j),所以第二层循环结束后要再处理一下最高位的进位
最后还需要去前导 0
具体请看下方代码
【代码】
(代码中,输入两个数分别为字符串 s,s1,s 和 s1 转换成数后为 n 数组和 m 数组存储,答案存放在 a 数组中,x 表示进位,len 表示最终答案长度)
#include <iostream>
#include <algorithm>
#include <string>
#define N 10005
using namespace std;
string s, s1;
int n[N], m[N], a[N], len, x;
int main() {
cin >> s >> s1;
for(int i = s.size() - 1; i >= 0; --i)
n[s.size() - i] = s[i] - 48;
for(int i = s1.size() - 1; i >= 0; --i)
m[s1.size() - i] = s1[i] - 48;
for(int i = 1; i <= s.size(); ++i) {
x = 0;
for(int j = 1; j <= s1.size(); ++j) {
a[i + j - 1] += x + n[i] * m[j];
x = a[i + j - 1] / 10;
a[i + j - 1] %= 10;
}
a[i + s1.size()] = x;
}
len = s.size() + s1.size();
while(!a[len] && len > 1)
--len;
for(int i = len; i >= 1; --i)
cout << a[i];
cout << endl;
return 0;
}
尾声
如果这篇博客对您(您的团队)有帮助的话,就帮忙点个赞,加个关注!
最后,祝您(您的团队)在 OI 的路上一路顺风!!!
┬┴┬┴┤・ω・)ノ Bye~Bye~