|
| 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 | +} |
0 commit comments