问题 X: 晨跑

题目描述

小明是个爱锻炼的好孩子,每天早晨他都会去自己家附近的一个公园晨跑。这个公园里有若干个花坛,这些花坛由一些小路连接。一天,小明在跑步的过程中突然想到这样一个问题:
如果自己可以选择从任何一个花坛开始,想跑步经过每一条小路,每条路至少经过一次,最后必须再回到开始时的花坛,那么最短的跑步路程是多长?

输入

输入包含多组测试数据。
每组输入的第一行为2个正整数n和m(n<=15,m<1000),n表示花坛的个数,m表示小路的个数。当n=0时,输入结束。
接下来m行,每行输入3个正整数s,e,l(1<=s,e<=n,1<=l<=5000),表示标号为s和e的花坛由一条小路相连,长度为l。任意两个花坛之间可能会由多条小路相连而且小路的长度也可能会相等。每条小路都是双向可通行的。从任何一条小路通过连接小路的花坛都可以到达其他任何一条小路。

输出

对于每组输入,输出小明满足题目要求要跑的最短路程。

样例输入 Copy

4 5
1 2 3
2 3 4
3 4 5
1 4 10
1 3 12
0

样例输出 Copy

41

代码

# 代码概述 该程序解决的是三位同学晨跑相遇的问题。输入三个正整数 $a, b, c$,表示三人分别每隔 $a$、$b$、$c$ 天晨跑一次。目标是计算他们下一次在晨跑中相遇的天数。 但注意:代码中实际计算的是 $\text{lcm}(\text{lcm}(a+1, b+1), c+1)$,即对输入值加1后再求最小公倍数。 --- # 代码解析 ```cpp #include<bits/stdc++.h> using namespace std; long long g(long long x, long long y){ long long t, n; if (x < y) { t = x; x = y; y = t; } n = x % y; while (n != 0) { n = x % y; x = y; y = n; } return x; } ``` - 函数 `g(x, y)` 计算两个数的最大公约数(GCD),使用的是辗转相除法(欧几里得算法)。 - 虽然开头有交换逻辑,但循环内未更新 `n` 导致冗余计算;**存在逻辑错误**:`n = x % y;` 在进入循环前已赋值,但在循环体末尾才更新 `x` 和 `y`,导致最后一次循环多算一次。正确写法应在循环内部只保留一次取模。 ✅ 正确版本应为: ```cpp while (y != 0) { n = x % y; x = y; y = n; } ``` ```cpp long long h(long long x, long long y){ return x / g(x, y) * y; } ``` - 函数 `h(x, y)` 计算最小公倍数(LCM),公式为: $$ \text{lcm}(x,y) = \frac{x \cdot y}{\gcd(x,y)} $$ - 使用先除后乘的方式可减少溢出风险(本代码顺序合理)。 ```cpp int main() { long long a, b, c; scanf("%lld%lld%lld", &a, &b, &c); long long k = h(h(a+1, b+1), c+1); printf("%lld\n", k); return 0; } ``` - 主函数读入 $a, b, c$,但计算的是 $(a+1), (b+1), (c+1)$ 的最小公倍数。 - 这意味着原题设定被修改:不是“每 $a$ 天跑一次”,而是“每 $a+1$ 天跑一次”。 ⚠️ **问题关键**:如果题目原意是“每 $a$ 天晨跑一次”(即周期为 $a$),那么代码应计算 $\text{lcm}(a, b, c)$,而非 $\text{lcm}(a+1, b+1, c+1)$。 👉 所以此代码与题目要求**不一致**,除非题设周期定义不同。 --- # 知识点 - **最大公约数(GCD)**:通过欧几里得算法求解,是计算 LCM 的基础,时间复杂度接近 $O(\log n)$。 - **最小公倍数(LCM)**:利用公式 $\text{lcm}(a,b)=\frac{a \cdot b}{\gcd(a,b)}$,适用于周期同步问题。 - **周期性事件同步**:多个周期事件首次同时发生的时刻为其周期的最小公倍数,前提是起始时刻相同(如第 0 天)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值