题目链接
一、题目简介
题目描述
给定一个超大整数 A 和一个普通整数 B,计算 A ÷ B 的商和余数。其中 A 的位数极大,无法用 C++ 内置整型、长整型存储,属于高精度大数 ÷ 低精度整数的经典模板题。
输入格式
- 第一行输入大整数 A(非负整数)
- 第二行输入整数 B
输出格式
- 第一行输出除法得到的商
- 第二行输出除法得到的余数
输入输出样例
输入
12345
123
输出
100
45
二、解题思路详细分析
1、问题难点
- 被除数 A 位数可达上千位,int、long long 完全存不下,只能用字符串 + 数组模拟存储。
- 本题是高精度 ÷ 低精度(大数 ÷ 普通整数),和高精度乘法逻辑不同,需要模拟手工除法从高位向低位计算。
- 运算过程中需要实时记录每一步的余数,最终单独输出余数。
- 需要处理商的前导零问题。
2、高精度除法核心原理(模拟手工竖式除法)
日常手写除法是从高位到低位依次计算,这也是本算法的核心流程:
- 字符串转数组:将大数按**原顺序(高位在前)**存入数组,除法必须从最高位开始运算,不需要倒序。
- 逐位试商 :遍历大数每一位,用
当前余数 × 10 + 当前位数字作为临时被除数。 - 计算商与新余数:商 = 临时被除数 / 除数,余数 = 临时被除数 % 除数,把商存入结果数组。
- 去除前导零:运算后商数组开头可能存在多余 0,需要过滤;若商全为 0,要保留一个 0。
- 输出结果:遍历商数组输出商,最后输出最终余数。
3、图文逻辑演示
以样例 12345 ÷ 123 举例:
大数数组:1, 2, 3, 4, 5,除数 B = 123,初始余数 rem = 0
- 第 1 位 1:rem = 0×10 + 1 = 1,商 1/123 = 0,存商 0,余数 1
- 第 2 位 2:rem = 1×10 + 2 = 12,商 12/123 = 0,存商 0,余数 12
- 第 3 位 3:rem = 12×10 + 3 = 123,商 123/123 = 1,存商 1,余数 0
- 第 4 位 4:rem = 0×10 + 4 = 4,商 4/123 = 0,存商 0,余数 4
- 第 5 位 5:rem = 4×10 + 5 = 45,商 45/123 = 0,存商 0,余数 45
商数组:0, 0, 1, 0, 0,去除前导零后得到 100,最终余数 45,与样例一致。
4、算法说明
- 适用场景:高精度大数 ÷ 普通整型
- 时间复杂度:O(n),n 为大数 A 的位数,效率极高
- 关键点:除法高位优先、实时更新余数、处理商的前导零
三、AC 代码(超详细注释)
cpp
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
// 设定数组最大长度,满足题目大数范围
const int MAXN = 10010;
// a 存储高精度被除数,ans 存储商
int a[MAXN], ans[MAXN];
int main()
{
string s; // 用字符串读取超大被除数
int b; // 除数,普通整型即可存储
cin >> s >> b;
int len = s.size();
// 1. 字符串转为数字数组,高位在前(除法不需要倒序)
for (int i = 0; i < len; i++)
{
a[i] = s[i] - '0';
}
int rem = 0; // 记录每一步的余数,初始为0
int cnt = 0; // 记录商的有效位数
// 2. 从高位到低位逐位模拟除法运算
for (int i = 0; i < len; i++)
{
// 拼接当前位:上一轮余数 * 10 + 当前数字
rem = rem * 10 + a[i];
// 计算当前位的商,存入答案数组
ans[cnt++] = rem / b;
// 更新余数
rem = rem % b;
}
// 3. 去除商的前导零
int pos = 0;
// 跳过开头多余的0,保证至少保留一个0
while (pos < cnt && ans[pos] == 0)
pos++;
// 特殊情况:商全部为0(被除数 < 除数)
if (pos == cnt)
cout << 0 << endl;
else
{
// 从第一个有效位开始输出商
for (int i = pos; i < cnt; i++)
cout << ans[i];
cout << endl;
}
// 4. 输出最终余数
cout << rem << endl;
return 0;
}
四、代码核心细节讲解
1、数组存储规则
高精度除法(大数 ÷ 低精度)必须高位在前,和高精度乘法、加法的倒序存储完全相反。因为手工除法是从最高位开始计算,顺序存储可以直接按下标遍历。
2、余数更新逻辑
核心公式:rem = rem * 10 + a[i]
把上一位运算剩下的余数,整体进一位(×10),再加上当前位数字,组成新的被除数。每一步做完除法后,只保留余数传递到下一位。
3、前导零处理
商数组开头会出现大量无效 0(例如样例中前两位 0),需要用 pos 指针跳过。
边界情况:如果被除数本身小于除数,所有商位都是 0,此时必须单独输出一个 0,不能无输出。
4、数据范围说明
题目中除数 B 在普通整型范围内,因此直接用 int 存储即可;被除数位数较大,用数组承载完全满足要求。
五、总结
本题是**高精度除法(大数 ÷ 低精度)**的标准模板题,也是算法竞赛高频基础题型。
核心要点:
- 大数用字符串读取,高位顺序存入数组
- 从左到右逐位运算,依靠
rem * 10 + 当前位拼接数字 - 单独处理商的前导零,最后输出余数