GESP二级的一道练习题,涉及循环和分支的基本功。这道题看似简单的思路反而容易让初学者栽跟头,因此被评为一道颇具巧思的练习,难度一颗星。
luogu-B2073 求小数的某一位
题目要求
题目描述
分数 a / b 化为小数后,小数点后第 n 位的数字是多少?
输入格式
三个正整数 a,b,n,相邻两个数之间用单个空格隔开。0 < a ≤ b ≤ 100,1 ≤ n ≤ 10000。
输出格式
一个数字。
输入 #1
1 2 1
输出 #1
5
题目分析
解题思路
这道题的核心在于模拟手算除法的过程,直接获取小数点后第n位的值,而不能先计算出整个小数或浮点数再取位。
- 读取输入的三个正整数a、b、n。
- 特殊情况处理:如果a等于b,那么结果是整数1(即1.000…),所以小数点后任意位都是0,直接输出0并结束。
- 核心模拟:我们从第1位开始,一直计算到第n位。
- 在计算第i位时,将当前被除数(初始为a)乘以10(相当于向后“借”一位)。
- 然后用这个新被除数除以b,得到的商就是小数点后第i位的数字。
- 将余数作为新的被除数,为计算下一位做准备。
- 当i等于n时,记录下的商即为答案。
为什么不能直接计算浮点数?
题目中n最大可达10000,任何基本数据类型(long long, double)都无法精确存储如此多位的精度,直接计算会因为精度丢失或溢出导致错误答案。因此,模拟手算除法是唯一可靠的方法。
示例代码
下面是清晰的C++实现代码,每一步都有注释说明:
#include<iostream>
using namespace std;
int main(){
int a, b, n;
cin >> a >> b >> n;
// 特殊情况:a == b,则结果为1,小数部分全为0
if (a == b) {
cout << 0;
return 0;
}
int digit; // 用于存储第n位的数字
// 模拟除法,求第n位小数
for (int i = 1; i <= n; i++) {
a = a * 10; // 被除数后补一位(相当于乘以10)
digit = a / b; // 计算当前位的商,即小数位
a = a % b; // 计算余数,作为下一位计算的被除数
}
cout << digit; // 输出小数点后第n位的数字
return 0;
}
在云栈社区与更多开发者交流,可以发现,这类考察基础但注重细节的题目,是检验编程基本功是否扎实的绝佳试金石。
关于题目来源:
“luogu-B2073”系列题目可以在洛谷题库进行在线评测。
|