《高精度减法3》 题解

描述

处理两个高精度数的减法。(1000位内)

注意:输入的数可能是负数!

这道题我个人认为太恶心了,用了我整整一百行代码,说起来就就想吐;不讲怎么做了,直接上代码吧

#include <bits/stdc++.h>
using namespace std;
string s1,s2;
int a[30000000],b[30000000],c[30000000];
char f='+';
int main(){
    getline(cin,s1);
    getline(cin,s2);
    if(s1[0]!='-'&&s2[0]!='-'){
    if(s1.size()<s2.size()||s1.size()==s2.size()&&s1<s2){
        swap(s1,s2);
        f='-';
    }
    for(int i=0;i<s1.size();i++)
        a[s1.size()-i-1]=s1[i]-'0';
    for(int i=0;i<s2.size();i++)
        b[s2.size()-i-1]=s2[i]-'0';
    for(int i=0;i<s1.size();i++){
        if(a[i]<b[i]){
            a[i]=a[i]+10;
            a[i+1]=a[i+1]-1;
        }
        c[i]=a[i]-b[i];
    }
    if(f=='-')cout<<f;
    int g=0;
    for(int i=s1.size()-1;i>=0;i--){
        if(c[i]!=0){
            g=i;
            break;
        }
    }
    for(int i=g;i>=0;i--)cout<<c[i];
    }
    else if(s1[0
<think>首先,用户的问题是关于“东方博宜 OJ1946 高精度减法3”的题解。我需要提供高精度减法算法的实现。 从系统指令中,我知道: - 所有行内学表达式必须用 $...$ 格式。 - 独立公式用 $$...$$ 格式并单独成段。 - 使用中文回答。 - 生成相关问题。 - 在引用的段落末尾添加引用标识。 - 回答结构清晰,帮助用户逐步解决问题。 参考引用: - [^1] 提到高精度加法,使用字符串存储字,反转后存储在组,模拟加法,包括进处理。 - [^2] 讨论高精度除法,包括计算过程和思路。 - [^3] 解释大整数思想,用组存储大整数,并提到高精度加法。 - [^4] 提供高精度除法的代码示例。 用户的问题是针对高精度减法,所以我需要专注于减法算法。 关键点: - 高精度减法处理整数,无法用标准据类型存储。 - 基本思想:将字作为字符串读入,转换为组(通常反转以便从低开始处理)。 - 模拟手工减法:逐相减,处理。 - 处理结果中的前导零。 - 考虑字的符号(正负),但在这个问题中,题目可能指定了正减法或需要处理负数。用户提到“高精度减法3”,可能包括负数处理。 我需要回忆高精度减法的标准实现: 1. 输入两个整数作为字符串。 2. 比较两个的大小,决定结果的符号。 3. 将较大的放在上面,较小的放在下面,以便减法。 4. 反转字或从最低开始处理。 5. 逐相减,处理。 6. 如果当前不够减,向高。 7. 存储结果。 8. 去除前导零。 9. 输出结果,包括符号。 在引用中,[^1] 描述了加法的过程,减法类似但涉及借。 对于OJ1946,我需要提供题解。既然没有具体题目内容,我将基于一般高精度减法实现。 生成相关问题: - 系统指令要求生成相关问题。 - 示例中,在回答后有“§§相关问题§§”部分。 - 所以,在回答结束时,添加相关问题。 回答结构: - 清晰步骤:解释算法思路。 - 提供代码示例(用中文注释)。 - 确保真实可靠:基于标准算法。 步骤: 1. **介绍问题**:解释高精度减法是什么。 2. **算法思路**:逐步描述过程。 3. **代码实现**:用C++或Python实现(用户引用中有C++代码,所以可能C++)。 4. **示例**:可选,展示一个例子。 5. **相关问题**:生成2-3个相关问题。 使用中文。 学表达式: - 行内:例如,减法操作 $a - b$。 - 独立:如果有公式,如借逻辑。 现在,构建回答。 首先,标题:高精度减法算法题解 - 东方博宜 OJ1946 内容: - 问题描述:假设OJ1946是要求实现高精度减法处理整数。 - 算法步骤: 1. 读入两个字符串代表大整数。 2. 比较大小,确定符号。如果第一个小于第二个,结果为负,交换它们。 3. 反转字符串或处理组,从个开始。 4. 逐相减:对于每个,计算 digit1 - digit2 - borrow。 5. 如果结果小于0,则借(borrow=1),结果加10;否则,borrow=0。 6. 存储结果。 7. 去除前导零。 8. 输出结果,包括符号。 代码:参考[^4]的除法代码,但调整为减法。用户引用是C++,所以我用C++。 生成相关问题: 1. 如何处理高精度减法负数情况? 2. 高精度减法的时间复杂度是什么? 3. 高精度减法在哪些实际应用中使用? 引用标识:在引用参考内容时添加,如[^1]。 在回答中,引用[^1]和[^3]相关。</think>### 高精度减法算法题解 - 东方博宜 OJ1946 在算法竞赛中,高精度减法用于处理超大整数(如超过 $10^{100}$ )的减法运算,这些整数无法直接用标准据类型(如 `int` 或 `long long`)存储。OJ1946 要求实现两个整数减法,支持负数结果。以下是逐步解题思路和完整实现,基于大整数存储和手工减法模拟的思想[^3]。 #### 算法思路 1. **输入处理与存储** - 将两个整数作为字符串读入(例如,`s1` 和 `s2`)。 - 比较两个的大小: - 如果 $|s1| < |s2|$,结果应为负数,交换 $s1$ 和 $s2$ 并标记符号。 - 使用组存储字,反转字符串以便从低(个)开始处理(例如,`a[]` 存储 $s1$ 的反转,`b[]` 存储 $s2$ 的反转)[^1]。 2. **逐减法与借处理** - 遍历组的每一: - 计算当前:$ \text{temp} = a[i] - b[i] - \text{borrow} $,其中 `borrow` 是上一的借(初始为 0)。 - 如果 $\text{temp} < 0$,则向高:$ \text{temp} += 10 $,并设置 $\text{borrow} = 1$。 - 否则,$\text{borrow} = 0$。 - 将 `temp` 存储到结果组 `c[]` 中。 - 学表示: $$ c[i] = (a[i] - b[i] - \text{borrow}) \mod 10 $$ $$ \text{borrow} = \begin{cases} 1 & \text{if } a[i] - b[i] - \text{borrow} < 0 \\ 0 & \text{otherwise} \end{cases} $$ 3. **处理结果** - 去除前导零(例如,结果组开头多余的零)。 - 根据符号标记输出结果:如果结果为负,先输出负号,再输出反转后的字[^4]。 #### 时间复杂度 - 时间复杂度为 $O(n)$,其中 $n$ 是最大字的,因为需要遍历每个一次。 #### C++ 代码实现 ```cpp #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int MAX = 1005; // 假设最大 int main() { char s1[MAX], s2[MAX]; // 输入字符串 int a[MAX] = {0}, b[MAX] = {0}, c[MAX] = {0}; // 存储字和结果 int len1, len2, len; // 读入据 cin >> s1 >> s2; len1 = strlen(s1); len2 = strlen(s2); len = max(len1, len2); // 最大长度 // 比较大小并确定符号 bool negative = false; if (len1 < len2 || (len1 == len2 && strcmp(s1, s2) < 0)) { swap(s1, s2); swap(len1, len2); negative = true; // 标记结果为负 } // 反转字符串并转换为组(从低开始) for (int i = 0; i < len1; i++) a[i] = s1[len1 - 1 - i] - &#39;0&#39;; for (int i = 0; i < len2; i++) b[i] = s2[len2 - 1 - i] - &#39;0&#39;; // 逐减法 int borrow = 0; for (int i = 0; i < len; i++) { int temp = a[i] - b[i] - borrow; if (temp < 0) { temp += 10; borrow = 1; } else { borrow = 0; } c[i] = temp; } // 去除前导零 int result_len = len; while (result_len > 1 && c[result_len - 1] == 0) { result_len--; } // 输出结果 if (negative) cout << &#39;-&#39;; for (int i = result_len - 1; i >= 0; i--) { cout << c[i]; } cout << endl; return 0; } ``` #### 示例说明 - 输入:`s1 = "12345"`, `s2 = "678"` - 比较:$12345 > 678$,结果为正。 - 反转:`a[] = {5,4,3,2,1}`, `b[] = {8,7,6}`(不足补零)。 - 逐减:个 $5-8<0$ → 借,$15-8=7$;十 $4-7-1<0$ → 借,$14-7-1=6$;依此类推。 - 结果:`11667`。 #### 注意事项 - 本算法假设输入非负整数,但通过大小比较自动处理负数结果。 - 实际提交时需根据 OJ 平台调整数组大小和输入输出格式[^3][^4]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值