Skip to content

Commit 24607d5

Browse files
committed
feat(template): 高精度 乘/除 高精度
1 parent 336a6bb commit 24607d5

8 files changed

+225
-52
lines changed

acwing/算法基础课/第一讲 基础算法/高精度/791. 高精度加法.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ using namespace std;
44

55
string a, b;
66

7-
vector<int> add(vector<int> &A, vector<int> &B) {
7+
vector<int> add(const vector<int> &A, const vector<int> &B) {
88
if (A.size() < B.size()) return add(B, A);
99
vector<int> C;
1010
int t = 0;
@@ -18,7 +18,7 @@ vector<int> add(vector<int> &A, vector<int> &B) {
1818
return C;
1919
}
2020

21-
void out(vector<int> &A) {
21+
void out(const vector<int> &A) {
2222
for (int i = A.size() - 1; i >= 0; i--) {
2323
cout << A[i];
2424
}

acwing/算法基础课/第一讲 基础算法/高精度/792. 高精度减法.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ using namespace std;
44

55
string a, b;
66

7+
// O(n)
78
// A>=B
8-
vector<int> sub(vector<int> &A, vector<int> &B) {
9+
vector<int> sub(const vector<int> &A, const vector<int> &B) {
910
vector<int> C;
1011
for (int i = 0, t = 0; i < A.size(); i++) {
1112
// 如果借过位,需要减去 t(t 是借位数量)
@@ -22,14 +23,15 @@ vector<int> sub(vector<int> &A, vector<int> &B) {
2223
return C;
2324
}
2425

25-
void out(vector<int> &A) {
26+
void out(const vector<int> &A) {
2627
for (int i = A.size() - 1; i >= 0; i--) {
2728
cout << A[i];
2829
}
2930
}
3031

32+
// O(n)
3133
// A < B
32-
bool cmp(vector<int> &A, vector<int> &B) {
34+
bool cmp(const vector<int> &A, const vector<int> &B) {
3335
if (A.size() != B.size()) {
3436
return A.size() < B.size();
3537
}

acwing/算法基础课/第一讲 基础算法/高精度/793. 高精度乘法-高精度乘以低精度.cpp

+6-9
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,19 @@ using namespace std;
55
string a;
66
int b;
77

8-
void out(vector<int> &A) {
8+
void out(const vector<int> &A) {
99
for (int i = A.size() - 1; i >= 0; i--) {
1010
cout << A[i];
1111
}
1212
}
1313

14-
vector<int> mul(vector<int> &A, int b) {
14+
vector<int> mul(const vector<int> &A, int b) {
1515
vector<int> C;
1616
int t = 0;
17-
for (int i = 0; i < A.size(); i++) {
18-
int val = A[i] * b + t;
19-
C.push_back(val % 10);
20-
t = val / 10;
21-
}
22-
while (t) {
23-
C.push_back(t % 10), t /= 10;
17+
for (int i = 0; i < A.size() || t; i++) {
18+
if (i < A.size()) t += A[i] * b;
19+
C.push_back(t % 10);
20+
t = t / 10;
2421
}
2522
while (C.size() > 1 && C.back() == 0) C.pop_back();
2623
return C;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
基本思想先将 A[i]*B[j] 放在 C[i+j] 上,然后过一遍 C 处理进位即可
3+
*/
4+
#include <iostream>
5+
#include <vector>
6+
using namespace std;
7+
8+
string a, b;
9+
10+
void out(const vector<int> &A) {
11+
for (int i = A.size() - 1; i >= 0; i--) {
12+
cout << A[i];
13+
}
14+
}
15+
16+
vector<int> mul(const vector<int> &A, const vector<int> &B) {
17+
vector<int> C(A.size() + B.size());
18+
for (int i = 0; i < A.size(); i++) {
19+
for (int j = 0; j < B.size(); j++) {
20+
C[i + j] += A[i] * B[j];
21+
}
22+
}
23+
int t = 0;
24+
for (int i = 0; i < C.size(); i++) {
25+
t += C[i];
26+
C[i] = t % 10;
27+
t /= 10;
28+
}
29+
while (C.size() > 1 && C.back() == 0) C.pop_back();
30+
return C;
31+
}
32+
33+
int main() {
34+
cin >> a >> b;
35+
vector<int> A, B;
36+
for (int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0');
37+
for (int i = b.size() - 1; i >= 0; i--) B.push_back(b[i] - '0');
38+
auto C = mul(A, B);
39+
out(C);
40+
return 0;
41+
}

acwing/算法基础课/第一讲 基础算法/高精度/794. 高精度除法-高精度除以低精度.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,17 @@ using namespace std;
66
string a;
77
int b;
88

9-
int div(vector<int> A, int b, vector<int>& C) {
10-
int r = 0;
9+
vector<int> div(const vector<int>& A, int b, int& r) {
10+
vector<int> C;
11+
r = 0;
1112
for (int i = A.size() - 1; i >= 0; i--) {
1213
r = r * 10 + A[i];
1314
C.push_back(r / b);
1415
r = r % b;
1516
}
1617
reverse(C.begin(), C.end());
1718
while (C.size() > 1 && C.back() == 0) C.pop_back();
18-
return r;
19+
return C;
1920
}
2021

2122
void out(vector<int>& A) {
@@ -29,7 +30,8 @@ int main() {
2930
vector<int> A;
3031
for (int i = a.length() - 1; i >= 0; i--) A.push_back(a[i] - '0');
3132
vector<int> C;
32-
int r = div(A, b, C);
33+
int r;
34+
C = div(A, b, r);
3335
out(C);
3436
cout << endl
3537
<< r << endl;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
减法模拟除法: https://www.bilibili.com/video/BV1iK4y1L7om/?spm_id_from=333.788.videocard.8
3+
4+
例子:
5+
78945/345
6+
78945-34500*2 = 9945 (不断减 34500 直到不够减为止)
7+
9945-3450*2 = 3045
8+
3045-345*8= 285
9+
因此,商就是 228, 余数就是 285
10+
11+
总时间复杂度: O(n-m * (n)),只能通过 8/12 个测试数据,因此能用「高精度/低精度」尽量不用「高精度/高精度」
12+
*/
13+
#include <algorithm>
14+
#include <iostream>
15+
#include <vector>
16+
using namespace std;
17+
18+
string a, b;
19+
20+
// A < B
21+
bool cmp(const vector<int> &A, const vector<int> &B) {
22+
if (A.size() != B.size()) {
23+
return A.size() < B.size();
24+
}
25+
for (int i = A.size() - 1; i >= 0; i--) {
26+
if (A[i] != B[i]) return A[i] < B[i];
27+
}
28+
return false;
29+
}
30+
// A>=B
31+
vector<int> sub(const vector<int> &A, const vector<int> &B) {
32+
vector<int> C;
33+
for (int i = 0, t = 0; i < A.size(); i++) {
34+
// 如果借过位,需要减去 t(t 是借位数量)
35+
t = A[i] - t;
36+
if (i < B.size()) t -= B[i];
37+
C.push_back((t + 10) % 10);
38+
// < 0 表示从高位借了一位出来了,所以 t = 1
39+
if (t < 0)
40+
t = 1;
41+
else
42+
t = 0;
43+
}
44+
while (C.size() > 1 && C.back() == 0) C.pop_back();
45+
return C;
46+
}
47+
48+
// O(n-m * (n)), 对于每个补 0 后的 B,最多执行 10 次时间复杂度为 O(n) 的高精度减法
49+
// 注意 A 会被修改,所以这里不使用引用
50+
// 不是很想写引用,因为别人调用的时候 div(A, B, A) 的话还得手动复制一遍 A 调用 div(A, B, A_copy),不然对结果 A 进行修改会使输入 A 出问题
51+
pair<vector<int>, vector<int>> div(vector<int> A, const vector<int> &B) {
52+
vector<int> C, R;
53+
int n = A.size(), m = B.size(), d = n - m;
54+
C.resize(d + 1, 0);
55+
// 枚举补 0 的个数
56+
for (int len = d; len >= 0; len--) {
57+
// Bp (B padded) 的构造可以外提优化,需要使用 deque 每次 pop_front,但是这里没有必要,因为时间复杂度主要瓶颈在下面循环的高精度减法上
58+
vector<int> Bp(len, 0);
59+
for (int x : B) Bp.push_back(x);
60+
61+
// A >= Bp
62+
while (!cmp(A, Bp)) {
63+
C[len] += 1;
64+
A = sub(A, Bp);
65+
}
66+
}
67+
while (C.size() > 1 && C.back() == 0) C.pop_back();
68+
R = A;
69+
return make_pair(C, R);
70+
}
71+
72+
void out(vector<int> &A) {
73+
for (int i = A.size() - 1; i >= 0; i--) {
74+
cout << A[i];
75+
}
76+
}
77+
78+
int main() {
79+
cin >> a >> b;
80+
vector<int> A, B;
81+
for (int i = a.length() - 1; i >= 0; i--) A.push_back(a[i] - '0');
82+
for (int i = b.length() - 1; i >= 0; i--) B.push_back(b[i] - '0');
83+
auto [C, R] = div(A, B);
84+
out(C);
85+
cout << endl;
86+
out(R);
87+
return 0;
88+
}

kick-start/template.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#include <algorithm>
22
#include <iostream>
3-
43
using namespace std;
54

65
int t;
@@ -14,4 +13,4 @@ int main() {
1413
printf("Case #%d: %d\n", i, solve());
1514
}
1615
return 0;
17-
}
16+
}

0 commit comments

Comments
 (0)