BISHI14 特殊的科学计数法¶
简单通过率 29.28%python3样例通过牛客 AC
一句话
把最多 1e5 位的大整数写成 a.b*10^c 的形式。
解题思路¶
这题考什么¶
「大数只按字符串看」的意识,外加一次严格的四舍五入。 N 可以有 1e5 位,一旦 int(N) 再转成浮点数就全毁了:float 只有约 16 位 有效数字,后面的位直接消失,指数也可能溢出成 inf。 但题目真正需要的信息只有三样:
也就是说,答案只与前 3 位数字和总位数有关,其余 99997 位一概不影响。 读入之后取个切片就够,复杂度就是读入本身的 O(|N|)。 浮点与舍入的背景见 23-浮点与科学计数法。
数据规模与复杂度¶
|N| <= 1e5,一次读入 + 常数次运算,O(|N|)。 时限「其他语言 6 秒」对这点计算量绰绰有余,难点全在正确性上。
坑在哪¶
- 不能用 round() 或 "%.1f" 做四舍五入,两者会从两个方向出错。 其一,round 用的是「四舍六入五成双」的银行家舍入,恰好是 0.5 时向偶数 靠拢:round(1.25, 1) 得 1.2,而题目要的是 1.3。 其二,二进制浮点存不下大多数十进制小数,9.95 存进 float 后实际是 9.9499999999999992...,于是 round(9.95, 1) 和 "%.1f" % 9.95 都给出 9.9, 而正确结果是进位到 10.0 再规格化成 1.0。 正确做法是 Decimal + ROUND_HALF_UP,且必须从字符串构造 Decimal, 一旦中途经过 float,误差在构造时就已经引入了;
- 进位可能溢出成 10.0(例如 N = 995... 时前三位是 995,9.95 进位成 10.0)。 题目要求 a ∈ [1,9],此时要重新规格化为 1.0,并把指数 c 加 1;
- 只看第 3 位就能定舍入方向:HALF_UP 语义下,第 3 位 >= 5 一定进位、 < 5 一定不进位,第 4 位往后有多少位、是什么都不改变结果。 所以切前 3 位是等价的,不是近似;
- 输出格式是 a.b*10^c,星号和尖号都不能少、也不能有空格; Decimal 经过 quantize(Decimal("0.1")) 后固定保留一位小数, 所以 3 会打印成 "3.0",这正是题目要的形式。
样例复核¶
N = 299792458:位数 9,c = 8;前三位 "299" -> 2.99 -> HALF_UP 到一位小数 得 3.0,输出 3.0*10^8,与样例一致。
参考实现¶
[:octicons-arrow-left-16: BISHI13](BISHI13.md) [BISHI15 :octicons-arrow-right-16:](BISHI15.md)