202 lines
5.1 KiB
Markdown
202 lines
5.1 KiB
Markdown
### 一、算法原理
|
||
|
||
1. 当输入的数很大时,可采用字符串方式接收。
|
||
|
||
2. 拆成一位一位的数字,把它们存在一个数组中,一个数组元素表示一位数字
|
||
|
||
数组中是这样存储的:
|
||
<center><img src='https://img2020.cnblogs.com/blog/8562/202109/8562-20210917094727724-1157818874.png'></center>
|
||
|
||
**倒序存储原因**:
|
||
|
||
在平常,数字从左到右依次为从高位到低位....可这里却与日常的习惯相反。
|
||
|
||
这是因为加法可能会产生进位,而数组在最前面加上数字是不可能的,但在尾巴处加上数字是好做的,所以,倒着放。
|
||
|
||
<center> <img src='https://img2020.cnblogs.com/blog/8562/202109/8562-20210917095858016-1722478475.png'></center>
|
||
|
||
|
||
### 二、[$AcWing$ $791$. 高精度加法](https://www.acwing.com/problem/content/793/)
|
||
|
||
```cpp {.line-numbers}
|
||
#include <bits/stdc++.h>
|
||
|
||
using namespace std;
|
||
const int N = 100010;
|
||
|
||
int a[N], b[N];
|
||
int al, bl;
|
||
void add(int a[], int &al, int b[], int &bl) {
|
||
int t = 0;
|
||
al = max(al, bl);
|
||
for (int i = 0; i < al; i++) {
|
||
t += a[i] + b[i];
|
||
a[i] = t % 10;
|
||
t /= 10;
|
||
}
|
||
if (t) a[al] = 1;
|
||
while (al > 0 && a[al] == 0) al--;
|
||
}
|
||
|
||
int main() {
|
||
string x, y;
|
||
cin >> x >> y;
|
||
for (int i = x.size() - 1; i >= 0; i--) a[al++] = x[i] - '0';
|
||
for (int i = y.size() - 1; i >= 0; i--) b[bl++] = y[i] - '0';
|
||
add(a, al, b, bl);
|
||
for (int i = al; i >= 0; i--) printf("%d", a[i]);
|
||
return 0;
|
||
}
|
||
```
|
||
|
||
### 三、[$AcWing$ $792$. 高精度减法](https://www.acwing.com/problem/content/794/)
|
||
|
||
```cpp {.line-numbers}
|
||
#include <bits/stdc++.h>
|
||
using namespace std;
|
||
|
||
const int N = 1e5 + 10;
|
||
int a[N], al;
|
||
int b[N], bl;
|
||
|
||
void sub(int a[], int &al, int b[], int &bl) {
|
||
int t = 0;
|
||
al = max(al, bl);
|
||
for (int i = 0; i < al; i++) {
|
||
t = a[i] - b[i] - t;
|
||
a[i] = (t + 10) % 10;
|
||
t < 0 ? t = 1 : t = 0;
|
||
}
|
||
while (al > 0 && a[al] == 0) al--;
|
||
}
|
||
|
||
int main() {
|
||
string x, y;
|
||
cin >> x >> y;
|
||
|
||
// 负号
|
||
if (x.size() < y.size() || (x.size() == y.size() && x < y)) {
|
||
printf("-");
|
||
swap(x, y);
|
||
}
|
||
|
||
for (int i = x.size() - 1; i >= 0; i--) a[al++] = x[i] - '0';
|
||
for (int i = y.size() - 1; i >= 0; i--) b[bl++] = y[i] - '0';
|
||
|
||
sub(a, al, b, bl);
|
||
|
||
for (int i = al; i >= 0; i--) printf("%d", a[i]);
|
||
return 0;
|
||
}
|
||
```
|
||
|
||
### 四、[$AcWing$ $793$. 高精度乘法](https://www.acwing.com/problem/content/795/)
|
||
|
||
```cpp {.line-numbers}
|
||
#include <bits/stdc++.h>
|
||
|
||
using namespace std;
|
||
const int N = 1e5 + 10;
|
||
int a[N], al;
|
||
int b[N], bl;
|
||
void mul(int a[], int &al, int b[], int &bl) {
|
||
int t = 0;
|
||
int c[N] = {0};
|
||
for (int i = 0; i < al; i++)
|
||
for (int j = 0; j < bl; j++)
|
||
c[i + j] += a[i] * b[j];
|
||
al += bl;
|
||
for (int i = 0; i < al; i++) {
|
||
t += c[i];
|
||
a[i] = t % 10;
|
||
t /= 10;
|
||
}
|
||
// 前导0
|
||
while (al > 0 && a[al] == 0) al--;
|
||
}
|
||
|
||
int main() {
|
||
string x, y;
|
||
cin >> x >> y;
|
||
for (int i = x.size() - 1; i >= 0; i--) a[al++] = x[i] - '0';
|
||
for (int i = y.size() - 1; i >= 0; i--) b[bl++] = y[i] - '0';
|
||
|
||
mul(a, al, b, bl);
|
||
for (int i = al; i >= 0; i--) printf("%d", a[i]);
|
||
return 0;
|
||
}
|
||
|
||
```
|
||
|
||
> **注**:网上对于高精度乘法,一般有高精乘低精 和 高精乘高精两种,学生们背起来太麻烦,容易出错,我把两个合并了一下,形成了一个模板,对于高精乘低精也可以兼容到,比如:
|
||
```cpp {.line-numbers}
|
||
int main() {
|
||
string x;
|
||
int y;
|
||
cin >> x >> y;
|
||
for (int i = x.size() - 1; i >= 0; i--) a[al++] = x[i] - '0';
|
||
b[0] = y, bl = 1;
|
||
mul(a, al, b, bl);
|
||
for (int i = al; i >= 0; i--) printf("%d", a[i]);
|
||
return 0;
|
||
}
|
||
```
|
||
|
||
### 五、[$AcWing$ $794$. 高精度除法](https://www.acwing.com/problem/content/796/)
|
||
|
||
```cpp {.line-numbers}
|
||
#include <bits/stdc++.h>
|
||
using namespace std;
|
||
|
||
const int N = 1e5 + 10;
|
||
int a[N], al, r;
|
||
void div(int a[], int &al, int b, int &r) {
|
||
r = 0;
|
||
for (int i = al - 1; i >= 0; i--) {
|
||
r = r * 10 + a[i];
|
||
a[i] = r / b;
|
||
r %= b;
|
||
}
|
||
// 去前导0
|
||
while (al > 0 && !a[al]) al--;
|
||
}
|
||
|
||
int main() {
|
||
string x;
|
||
int y;
|
||
|
||
cin >> x >> y;
|
||
|
||
for (int i = x.size() - 1; i >= 0; i--) a[al++] = x[i] - '0';
|
||
// 高精度除法
|
||
div(a, al, y, r);
|
||
|
||
// 输出
|
||
for (int i = al; i >= 0; i--) printf("%d", a[i]);
|
||
puts("");
|
||
printf("%d\n", r);
|
||
return 0;
|
||
}
|
||
```
|
||
|
||
### 六、保留结果$K$位
|
||
```cpp {.line-numbers}
|
||
// 高精乘高精,限长K(K<=100,不是很大)
|
||
void mul(int a[], int b[]) {
|
||
int t = 0;
|
||
int c[N] = {0};
|
||
for (int i = 0; i < K; i++)
|
||
for (int j = 0; j < K; j++)
|
||
if (i + j < K) c[i + j] += a[i] * b[j]; // 防止越界,需要加上i+j<K的限制
|
||
|
||
for (int i = 0; i < K; i++) {
|
||
t += c[i]; // 进位与当前位置的和
|
||
a[i] = t % 10; // 余数保留下来
|
||
t /= 10; // 进位
|
||
}
|
||
}
|
||
|
||
// 去前导0
|
||
//int al=K;
|
||
//while (al > 0 && a[al]==0) al--;
|
||
``` |