1 条题解
-
0
自动搬运
来自洛谷,原作者为

chen_zhe
Aya 敲可爱的~搬运于
2025-08-24 21:16:55,当前版本为作者最后更新于2024-12-15 19:30:34,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
欢迎报名洛谷网校,期待和大家一起进步!
本题考查数论。
(超时做法) 使用循环结构,让变量 从第 秒循环到第 秒。每 秒鼓掌一次就是指 能够被 整除的时候鼓掌,每 秒鼓掌一次同理。因此编写一个循环,统计有多少个这样的 即可。
参考代码(部分):
for (int i = 1; i <= n; i++) { if (i % x == 0 || i % y == 0) cnt++; }这样的代码会 TLE(超时),是因为题目中的 最大可以到 ,计算机一秒钟运行不了那么多运算。因此,我们需要优化计算流程。
(正确做法)
我们可以使用数学方式统计有多少秒鼓掌。
在 秒内,A 班每 秒鼓掌一次,一共会鼓掌 次,其中 表示下取整,例如 ,写作代码就是
n / x( 和 都是整型变量)在 秒内,B 班每 秒鼓掌一次,一共会鼓掌 次。
但是,A 班和 B 班会有重叠的鼓掌时间,重叠的周期即为 的最小公倍数,即 。最小公倍数指的是,最小的正整数 ,使得 能同时整除 ,例如 的最小公倍数是 , 的最小公倍数是 。
因此,额外减去 次鼓掌即可。问题在于如何求出 呢?实际上我们可以求出最大公约数 (即:最大的正整数 ,使得 能同时整除 ,例如 和 的最大公约数是 ),然后使用这个转化公式,即可求出 了:
$$\operatorname{lcm}(x,y)=\dfrac{x\times y}{\gcd(x,y)} $$最大公约数如何求出呢?有三种做法。
- 第一种做法是编写一个循环,让循环变量
z从 和 中的最小值开始不断自减,逐个判断是否能够同时满足x % z == 0和y % z == 0,若能满足则第一个被发现的 就是最大公约数。这种做法效率最慢,但是足以通过本题。 - 第二种做法是使用辗转相除法,利用性质 进行递归,从而快速计算出最大公约数,运算效率比第一种做法快。
- 第三种做法是使用库函数
__gcd(x, y)(仅限 G++ 编译器)或者std::gcd(x, y)(仅限 C++17 以后的语言标准,头文件为numeric)计算,这个做法效率上和第二种做法可以认为是一致的,但是正式赛无法使用std::gcd(x, y)。
参考代码:
int gcd(int x, int y) { //第一种做法 int z = min(x, y); while (!(x % z == 0 && y % z == 0)) z--; return z; } int gcd(int x, int y) { //第二种做法 return !y ? x : gcd(y, x % y); } cout << n / x + n / y - n / (x / gcd(x, y)*y) << endl; - 第一种做法是编写一个循环,让循环变量
- 1
信息
- ID
- 11146
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 2
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者