题解
n进制的减法
1 条题解
-
0
解题思路
平时我们用十进制:满 10 进 1。n 进制就是满 n 进 1。比如二进制只有 0 和 1 两个数字,满 2 就进位。
高精度减法模拟竖式:
- 把两个 n 进制数按位存进数组,个位放前面。
- 从个位开始逐位相减:a[i] - b[i],如果不够减,就向高位借 1。借来的 1 在 n 进制里等于 n,所以不够减时就加上 n,同时记录借位。
- 减完去掉前面的 0(全是 0 就输出一个 0)。
还要注意一个问题:题目没保证 a 一定比 b 大。如果 a < b,结果是负数。所以要先比较两个数的大小:先比长度,长度一样就从高位往低位比。a 小的话就交换 a、b,并在答案前面加一个负号。
参考代码
// 用途:计算两个 n 进制正整数的差 a-b(高精度减法,n 进制) #include <iostream> using namespace std; char sa[1005], sb[1005]; int a[1005], b[1005], res[1005]; int main() { int n; cin >> n >> sa >> sb; int la = 0, lb = 0; while (sa[la]) la++; while (sb[lb]) lb++; // 判断 a 和 b 谁大(先比长度,再比高位) int neg = 0; if (la < lb) neg = 1; else if (la == lb) { for (int i = 0; i < la; i++) { if (sa[i] != sb[i]) { neg = (sa[i] < sb[i]); break; } } int same = 1; for (int i = 0; i < la; i++) if (sa[i] != sb[i]) { same = 0; break; } if (same) { cout << 0 << endl; return 0; } // a 等于 b,差为 0 } // 转成数字数组,个位放最前面 for (int i = 0; i < la; i++) a[i] = sa[la - 1 - i] - '0'; for (int i = 0; i < lb; i++) b[i] = sb[lb - 1 - i] - '0'; // 如果 a 比 b 小,交换,让 a 始终是较大的数 if (neg) { for (int i = 0; i < 1005; i++) { int t = a[i]; a[i] = b[i]; b[i] = t; } int t = la; la = lb; lb = t; } // n 进制减法:每一位借位处理 int borrow = 0, len = la; for (int i = 0; i < len; i++) { int v = a[i] - b[i] - borrow; if (v < 0) { v += n; borrow = 1; } else borrow = 0; res[i] = v; } while (len > 1 && res[len - 1] == 0) len--; // 去掉前导 0 if (neg) cout << "-"; for (int i = len - 1; i >= 0; i--) cout << res[i]; cout << endl; return 0; }复杂度分析
设两个数分别有 la 位和 lb 位。比较大小、转数组、逐位相减都是 O(la+lb),总时间复杂度 O(la+lb)。
- 1