[Code+#1] 晨跑

GitHub跳转原题关系图返回列表

三人下一次相遇的天数就是三个晨跑周期的最小公倍数,先求 lcm(a,b) 再与 c 合并即可。

OJ: luogu

题目 ID: P4057

难度:入门

标签:数论最小公倍数python

日期: 2026-06-18 22:31

题意

三个人在第 00 天一起晨跑。
之后他们分别每 aabbcc 天晨跑一次。
要求输出下一次三个人再次相遇是第几天。

思路

先看一个可以直接验证想法的朴素解:

从第 11 天开始一天天枚举,第一次同时满足:

  • daymoda=0day \bmod a = 0
  • daymodb=0day \bmod b = 0
  • daymodc=0day \bmod c = 0

时,这一天就是答案。

cpp
// brute.cpp:小数据暴力解,用来帮助理解题意并辅助对拍。
#include <bits/stdc++.h>
using namespace std;

using ll = long long;

ll a, b, c;

void solve() {
    ll day = 1;
    while (true) {
        if (day % a == 0 && day % b == 0 && day % c == 0) {
            cout << day << '\n';
            return;
        }
        day++;
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> a >> b >> c;
    solve();

    return 0;
}

这个暴力写法可以帮助理解题意,但本质上它只是在找一个最小的正整数 dayday,使得它同时是 a,b,ca,b,c 的倍数。

换句话说,题目其实就在问:

lcm(a,b,c)\operatorname{lcm}(a, b, c)

而两个数的最小公倍数可以用:

lcm(x,y)=x/gcd(x,y)×y\operatorname{lcm}(x, y) = x / \gcd(x, y) \times y

来计算。

所以三个数直接分两步合并就行:

  1. 先求 lcm(a,b)\operatorname{lcm}(a, b)
  2. 再求 lcm(lcm(a,b),c)\operatorname{lcm}(\operatorname{lcm}(a, b), c)

正式代码就是按这个式子直接计算答案。

Python 知识

  • math.lcm 可以接收多个整数,直接计算三个周期的最小公倍数。
  • map(int,input().split()) 把一行字符串惰性转换成整数参数。
  • lcm(*values) 中的 * 把可迭代对象解包成位置参数。
  • Python 整数任意精度,不需要 C++ 的 __int128 和手写输出。
  • /home/rainboy/mycode/hugo-blog/content/program_language/python/map_reduce_filter.mdmap 与多参数归约。
  • /home/rainboy/mycode/hugo-blog/content/program_language/python/cpp_to_python_pitfalls.md:整数溢出差异。

代码

python
from math import lcm


print(lcm(*map(int, input().split())))

复杂度

时间复杂度是 O(logmax(a,b,c))O(\log \max(a,b,c)),空间复杂度是 O(1)O(1)

总结

这题虽然包装成"晨跑相遇",本质就是一个周期同步问题。

一旦看出"下一次同时出现"对应"最小公倍数",题目就变成了非常直接的 gcd/lcm 模板题。