top1编程
← 返回题目
题解

守护者的问题

1 条题解

  • 0
    @ 2026-8-4 1:13:28

    解题思路

    两个大整数的位数在 10 到 500 之间,不能用普通的 int 或 long long,要用高精度减法。

    思路还是像列竖式一样,从个位开始一位一位减:

    1. 把两个数当字符串读进来。
    2. 先比较谁大:位数多的数大;位数一样,就从最高位往低位一位一位比。
    3. 用大的数减小的数:把大数放前面,逐位相减,哪一位不够减就向高一位借 1(那一位加 10)。
    4. 如果答案是负数(小的减大的),输出的时候要加负号。
    5. 最后从高位往低位输出,去掉前导 0。

    参考代码

    // 用途:两个超级大的整数(10~500位)相减,输出差
    // 大整数用字符数组读入,倒序存入数组逐位相减(高精度减法)
    #include <iostream>
    using namespace std;
    int main() {
        char n[505], m[505];
        int a[505] = {0}, b[505] = {0}, r[505] = {0};
        cin >> n >> m;
        int ln = 0, lm = 0;
        while (n[ln]) ln++;   // n的位数
        while (m[lm]) lm++;   // m的位数
        // 比较n和m谁大(先比位数,再比高位)
        int neg = 0;
        if (ln < lm) neg = 1;
        else if (ln == lm) {
            for (int i = 0; i < ln; i++) {
                if (n[i] < m[i]) { neg = 1; break; }
                if (n[i] > m[i]) break;
            }
        }
        char *big = neg ? m : n, *small = neg ? n : m; // 大的放前面
        int lbig = neg ? lm : ln, lsmall = neg ? ln : lm;
        for (int i = 0; i < lbig; i++) a[i] = big[lbig - 1 - i] - '0';  // 倒序
        for (int i = 0; i < lsmall; i++) b[i] = small[lsmall - 1 - i] - '0';
        for (int i = 0; i < lbig; i++) {   // 逐位相减
            r[i] = a[i] - b[i];
            if (r[i] < 0) { r[i] += 10; a[i + 1]--; } // 不够减就借位
        }
        if (neg) cout << '-';              // 结果为负数时加负号
        int len = lbig;
        while (len > 1 && r[len - 1] == 0) len--;      // 去掉前导0
        for (int i = len - 1; i >= 0; i--) cout << r[i];
        return 0;
    }
    

    复杂度分析

    减法要处理所有位,n 最多 500 位,时间复杂度是 O(n),空间复杂度也是 O(n),1 秒内轻松完成。

    • 1