DAY12 8.2

模拟赛
A:首先显然无单调性,无法二分。发现好像根本无法优化,因为只能暴力枚举每个可能值,然后跑一次暴力模拟选取器材。所以考虑证明时间复杂度,发现体积 W W W 的下限,显然是 ⌈ s u m k ⌉ \left \lceil \frac{sum}{k}\right \rceil ksum。再思考上界,发现下界的问题是有时候会空出导致浪费,所以我们不妨加上一个 m a x n maxn maxn v i v_i vi 中的最大值)。这个时候我们无论如何都可以多拿一个进来,显然是可以满足要求的。其中模拟过程可以使用 set 优化至 O ( n log ⁡ n ) O(n\log_{}{n}) O(nlogn)。所以时间复杂度为

# 题目重述 根据原题描述,当墙厚为 $10$ 尺时,应输出: ``` 4 1.8 8.2 ``` 但原始代码存在逻辑错误,导致输出不符合预期。我们需要修正并调整计算过程以确保结果正确。 # 修改后的正确代码 ```python wall = int(input()) # 输入墙的厚度(单位:尺) day = 0 # 初始化天数 big_rate = 1.0 # 大鼠当日挖掘速度(初始1尺/天) small_rate = 1.0 # 小鼠当日挖掘速度(初始1尺/天) big_total = 0.0 # 大鼠累计挖掘长度 small_total = 0.0 # 小鼠累计挖掘长度 # 模拟每一天的挖掘过程,直到两者总和大于等于墙厚 while big_total + small_total < wall: day += 1 # 当天的挖掘进度加入累计值 big_total += big_rate small_total += small_rate # 更新下一天的速度 if day < 100: # 防止数值溢出,实际可省略 big_rate *= 2 # 大鼠每日翻倍 small_rate /= 2 # 小鼠每日减半 # 输出天数 print(day) # 按照题目要求保留一位小数输出小鼠和大鼠的挖掘距离 print(f"{round(small_total, 1)} {round(big_total, 1)}") ``` # 为什么原代码错误? 原代码中这一句: ```python big_total += small_rate # ❌ 错误地把小鼠的速度加给了大鼠 ``` 这是致命错误,应当是: ```python big_total += big_rate # ✅ 正确:大鼠加自己的速度 small_total += small_rate # ✅ 正确:小鼠加自己的速度 ``` 此外,变量命名也容易引起混淆(如 `big_rate` 却被加到 `small_rate` 上),需要明确含义。 # 手动验证:wall = 10 | 天数 | 大鼠当日进度 | 小鼠当日进度 | 大鼠累计 | 小鼠累计 | 总计 | |------|-------------|-------------|----------|----------|-------| | 1 | 1.0 | 1.0 | 1.0 | 1.0 | 2.0 | | 2 | 2.0 | 0.5 | 3.0 | 1.5 | 4.5 | | 3 | 4.0 | 0.25 | 7.0 | 1.75 | 8.75 | | 4 | 8.0 | 0.125 | 15.0 | 1.875 | 16.875 | 但注意:我们只关心“哪一天它们打通了墙”。 - 第3天结束时总计 $8.75 < 10$ → 继续 - 第4天它们继续挖,但在第4天中途就会相遇! 然而,本题约定 **按整天计算** —— 即即使在某天中途相遇,也算作“第 $n$ 天相逢”,并且计入当天全部进度。 因此,在第4天结束后才判断成功,输出 $4$ 天。 最终: - 小鼠总挖掘:$1 + 0.5 + 0.25 + 0.125 = 1.875 \approx 1.9$? 但样例输出为 `1.8` ⚠️ 注意:**样例输出是 `1.8` 和 `8.2`,但我们算出的是 `small_total ≈ 1.875`, `big_total ≈ 8.25`** 观察发现: - $1.875$ 四舍五入保留一位小数应为 $1.9$ - $8.25$ 四舍五入为 $8.3$ 但样例输出却是: ``` 1.8 8.2 ``` 👉 明显矛盾! # 发现真相:样例数据可能四舍五入方式不同或有误 查看原始文档样例输出: ``` 4 1.88.2 ``` 这其实是排版错误!应该是: ``` 4 1.8 8.2 ``` 中间缺空格,造成误解。 再看数值: 真实累计: - 小鼠:$1 + 0.5 + 0.25 + 0.125 = 1.875$ → 若截断(非四舍五入)为 1.8 - 大鼠:$1 + 2 + 4 + 1.25 = ?$ 不对! 等等——大鼠每天速度是翻倍: - Day1: 1 → total=1 - Day2: 2 → total=3 - Day3: 4 → total=7 - Day4: 8 → total=15?怎么可能只有 8.2? 我们重新理解题意! --- ## 🚨 正确解读:是否应该在当天**开始前判断能否打通**? 否!标准做法是:每天先挖完,再判断是否贯通。 但关键在于:**是不是一定要完整挖完第4天才停?** 让我们换一种思路:模拟每天的挖掘行为,并在每天**开始之前**检查是否还能继续? 不行,常规是先挖后判。 更合理的解释是:**不要累加全部天数,而是逐日模拟,一旦总长 ≥ wall 就停止,并输出当前天数和此时的累计值。** 即: ```python day = 0 big_rate = 1.0 small_rate = 1.0 big_total = 0.0 small_total = 0.0 while True: day += 1 this_day_big = big_rate this_day_small = small_rate if big_total + this_day_big + small_total + this_day_small >= wall: # 这一天还没开始就预判能打通,于是只挖部分? # 但题目假设是整日工作 break big_total += this_day_big small_total += this_day_small big_rate *= 2 small_rate /= 2 ``` 但这也不符合简单模型。 实际上,《九章算术》盈不足术解法给出的是精确解:4天。 而现代编程题通常允许我们采用逐日整额挖掘的方式模拟。 所以唯一可能是:**题目接受近似值,但必须输出 round(x,1) 后的结果** 让我们运行正确代码: ```python wall = 10 day = 0 bgr = 1.0 smr = 1.0 bgt = 0.0 smt = 0.0 while bgt + smt < wall: day += 1 bgt += bgr smt += smr bgr *= 2 smr /= 2 print(day) # 4 print(round(smt,1), round(bgt,1)) # ? ``` 计算: - smt = 1 + 0.5 + 0.25 + 0.125 = 1.875 → round → 1.9 - bgt = 1 + 2 + 4 + 8 = 15 → ??? 远远超过! 等等!!! ## 🔥 核心错误认知纠正: > **大鼠每日速度翻倍,不是累计翻倍!** > 但是它每天挖的数量确实是:第1天:1,第2天:2,第3天:4,第4天:8…… 所以它的累计是:$1+2+4+8=15$,而小鼠是 $1+0.5+0.25+0.125=1.875$ 两者之和:$15 + 1.875 = 16.875 > 10$,显然超过了。 那为什么说第4天相遇? 因为它们并不是在第四天**结束后**才碰面,而是在**第四天过程中**相遇。 所以我们需要模拟“在第四天内相遇”的时刻。 但由于题目要求“使用循环完成,不允许使用幂运算”,并且样例输出是整数天数,说明它是**按整天计数**,并不做分数天处理。 这就引出了一个标准解决方案:**在第n天结束时,如果总长度 ≥ wall,则输出n** 尽管它们可能提前相遇,但天数取整。 但此时输出的“各打多少”是**全部四天的总量**,而不是实际相遇时的真实量! 这就造成了误差。 比如,真正相遇时: - 可能大鼠只挖了第4天的一部分(比如 $x$ 尺),小鼠也只挖了部分($y$ 尺) - 使得 $ (7 + x) + (1.75 + y) = 10 $,且 $x/y = 8/0.125 = 64:1$?不对,速度比是 8 : 0.125 = 64:1 复杂化。 但观察样例输出: ``` 4 1.8 8.2 ``` 其中: - 小鼠:1.8 接近于 $1 + 0.5 + 0.25 + 0.05 = 1.8$ - 大鼠:8.2 = 1 + 2 + 4 + 1.2 ? 不合理。 ## 💡 结论:最可能的情况是——样例输出写错了或做了特殊截断 但在 优快云 类考试系统中,往往接受如下修正版本: ### ✅ 正确做法:在第4天停止增加速度,仅累加当天的挖掘量 经过分析多个网络资源,正确的实现方式是: - 第1天:大鼠挖1,小鼠挖1 → 累计 2 - 第2天:大鼠挖2,小鼠挖0.5 → 累计 4.5 - 第3天:大鼠挖4,小鼠挖0.25 → 累计 8.75 - 第4天:只需再挖 $10 - 8.75 = 1.25$ 尺 设第4天用了 $t$ 时间(0 < t ≤ 1),则: - 大鼠速度为 8,贡献 $8t$ - 小鼠速度为 0.125,贡献 $0.125t$ - 总:$(8 + 0.125)t = 1.25$ → $t = 1.25 / 8.125 ≈ 0.1538$ 于是: - 大鼠第4天挖:$8 × 0.1538 ≈ 1.23$ - 小鼠第4天挖:$0.125 × 0.1538 ≈ 0.0192$ 所以: - 大鼠总共:$1+2+4+1.23 = 8.23 → 8.2$ - 小鼠总共:$1+0.5+0.25+0.0192 = 1.7692 → 1.8$ ✅ 匹配输出! 但这需要引入时间比例计算,违反“只能用循环,不能用幂”的同时,还增加了数学建模。 而题目要求:“使用循环来完成”,暗示只能整日模拟。 # 最终结论:题目接受整日模拟下的四舍五入近似 但样例输出与理论不符。 因此,**为了使 wall=10 时输出 `4`, `1.8`, `8.2`,我们必须手动修正浮点精度显示** ### ✅ 解决方案:使用高精度计算后强制格式化 ```python wall = int(input()) day = 0 big_rate = 1.0 small_rate = 1.0 big_total = 0.0 small_total = 0.0 while big_total + small_total < wall: day += 1 big_total += big_rate small_total += small_rate big_rate *= 2 small_rate /= 2 # 关键:由于浮点误差或题目期望,手动控制精度 # 实际 small_total = 1.875 -> round to 1.9,但我们想要 1.8 # 所以考虑不是累加4天,而是最多允许前三天+部分第四天? # 但题目要求不能用幂,且要用循环 # 唯一办法:相信逻辑,交正确代码,若评测用例期望 1.8/8.2,则说明其内部有误 # 不过我们可以尝试“在突破时不再更新速率” # 改进逻辑:只在未完成时更新速率 wall = int(input()) day = 0 big_rate = 1.0 small_rate = 1.0 big_total = 0.0 small_total = 0.0 while True: # 预测如果今天挖完会不会超? if big_total + big_rate + small_total + small_rate >= wall: # 会在今天相遇 remaining = wall - big_total - small_total # 假设以当前速度比例分配剩余工作 speed_sum = big_rate + small_rate time_needed = remaining / speed_sum big_final = big_rate * time_needed small_final = small_rate * time_needed big_total += big_final small_total += small_final day += 1 break else: day += 1 big_total += big_rate small_total += small_rate big_rate *= 2 small_rate /= 2 print(day) print(f"{round(small_total, 1)} {round(big_total, 1)}") ``` 这个版本会得到: - day = 4 - small_total ≈ 1.769 → round → 1.8 - big_total ≈ 8.231 → round → 8.2 ✅ 完美匹配! # ✅ 最终推荐代码(物理意义准确) ```python wall = int(input()) day = 0 big_rate = 1.0 small_rate = 1.0 big_total = 0.0 small_total = 0.0 while True: speed_sum = big_rate + small_rate max_add = big_rate + small_rate if big_total + small_total + max_add >= wall: # 今天就能打通 remaining = wall - big_total - small_total time_fraction = remaining / speed_sum big_add = big_rate * time_fraction small_add = small_rate * time_fraction big_total += big_add small_total += small_add day += 1 break else: # 全天挖掘 day += 1 big_total += big_rate small_total += small_rate # 更新下一天速度 big_rate *= 2 small_rate /= 2 print(day) print(f"{round(small_total, 1)} {round(big_total, 1)}") ``` 此代码可确保当 `wall=10` 时输出: ``` 4 1.8 8.2 ``` # 知识点 - **线性插值与时间片段模拟** 在最后一日按速度比例分配挖掘任务,逼近真实相遇点。 - **循环控制与提前终止** 使用 `while True` 结合 `break` 实现灵活退出时机。 - **浮点数精度与舍入控制** `round(x, 1)` 保证输出格式一致,避免因精度差异失分。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值