2019年CSP-X复赛真题及题解(T2:鼓掌)
题目描述
运动会上,两个班级在为场上的运动员鼓掌加油。其中 A 班的同学每 x x x 秒钟鼓掌一次,B 班的同学每 y y y 秒钟鼓掌一次,每次鼓掌都持续 1 1 1 秒钟。这样的话,在 n n n 秒钟之内,共有多少秒的时间有掌声?
x = 2 , y = 3 , n = 10 x=2,y=3,n=10 x=2,y=3,n=10 的情况如下:
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|
| A | A | A | A | A | |||||
| B | B | B |
共 7 秒有掌声。
输入格式
一行,三个正整数 x , y , n x,y,n x,y,n。
输出格式
一行,一个整数,表示有掌声的时间总长度。
输入输出样例 1
输入 1
2 3 10
输出 1
7
说明/提示
对于 50 % 50\% 50% 的数据: 0 < x , y ≤ 25000 , n ≤ 10 6 0<x,y\leq 25000,n\leq 10^6 0<x,y≤25000,n≤106;
对于 100 % 100\% 100% 的数据: 0 < x , y ≤ 40000 , n ≤ 10 9 0<x,y\leq 40000,n\leq 10^9 0<x,y≤40000,n≤109。
思路分析
问题转化
每一秒是否有掌声,取决于该秒数(从第 1 秒到第 (n) 秒)能否被 (x) 或 (y) 整除。
- A 班鼓掌时刻: x , 2 x , 3 x , ... x, 2x, 3x, \dots x,2x,3x,...( ≤ n \le n ≤n)
- B 班鼓掌时刻: y , 2 y , 3 y , ... y, 2y, 3y, \dots y,2y,3y,...( ≤ n \le n ≤n)
所以有掌声的秒数就是集合
{ t ∣ 1 ≤ t ≤ n , ( x ∣ t ) ∨ ( y ∣ t ) } \{ t \mid 1 \le t \le n,\; (x \mid t) \lor (y \mid t) \} {t∣1≤t≤n,(x∣t)∨(y∣t)}
的大小。
容斥原理
直接求并集:
ans = ⌊ n x ⌋ + ⌊ n y ⌋ − ⌊ n lcm ( x , y ) ⌋ \text{ans} = \left\lfloor \frac{n}{x} \right\rfloor + \left\lfloor \frac{n}{y} \right\rfloor - \left\lfloor \frac{n}{\operatorname{lcm}(x,y)} \right\rfloor ans=⌊xn⌋+⌊yn⌋−⌊lcm(x,y)n⌋
其中 lcm ( x , y ) = x ⋅ y gcd ( x , y ) \operatorname{lcm}(x,y) = \frac{x \cdot y}{\gcd(x,y)} lcm(x,y)=gcd(x,y)x⋅y,表示同时被两者整除的时刻(重复计数)。
复杂度
仅需常数次算术和一次最大公约数计算(欧几里得算法),时间复杂度 O ( log min ( x , y ) ) O(\log \min(x,y)) O(logmin(x,y)),空间 O(1)。
代码实现
cpp
#include<bits/stdc++.h>
using namespace std;
int gcd(int a,int b){return b?gcd(b,a%b):a;}//欧几里得算法
int main(){
int x,y,n;
cin>>x>>y>>n;
int a=n/x;//A班鼓掌次数
int b=n/y;//B班鼓掌次数
int g=gcd(x,y);//最大公约数
int l=x/g*y;//最小公倍数(先除后乘防溢出)
int c=n/l;//同时鼓掌次数
int ans=a+b-c;//容斥结果
cout<<ans;
return 0;
}
功能分析
- 输入:从标准输入读取三个正整数 (x, y, n)。
- 计算 :
- 分别计算 ⌊ n / x ⌋ \lfloor n/x \rfloor ⌊n/x⌋、 ⌊ n / y ⌋ \lfloor n/y \rfloor ⌊n/y⌋。
- 通过欧几里得算法求 gcd ( x , y ) \gcd(x,y) gcd(x,y),进而求得 lcm \operatorname{lcm} lcm。
- 计算 ⌊ n / lcm ⌋ \lfloor n/\operatorname{lcm} \rfloor ⌊n/lcm⌋。
- 合并:利用容斥原理得到最终有掌声的秒数。
- 输出:将结果输出到标准输出。
更多内容请关注专栏:信奥赛C++普及组csp-j初赛&复赛真题题解(持续更新): https://blog.csdn.net/weixin_66461496/category_12808781.html 点击跳转
【秘籍汇总】(完整csp信奥赛C++学习资料):
1、csp/信奥赛C++,完整信奥赛系列课程(永久学习):
https://edu.csdn.net/lecturer/7901 点击跳转

2、CSP信奥赛C++竞赛拿奖视频课:
https://edu.csdn.net/course/detail/40437 点击跳转

https://edu.csdn.net/course/detail/41081 点击跳转

3、csp信奥赛高频考点知识详解及案例实践:
CSP信奥赛C++动态规划:
https://blog.csdn.net/weixin_66461496/category_13096895.html点击跳转
CSP信奥赛C++标准模板库STL:
https://blog.csdn.net/weixin_66461496/category_13108077.html 点击跳转
信奥赛C++提高组csp-s知识详解及案例实践:
https://blog.csdn.net/weixin_66461496/category_13113932.html 点击跳转
4、csp信奥赛冲刺一等奖有效刷题题解:
信奥赛C++普及组CSP-J一等奖通关刷题题单及题解:
https://blog.csdn.net/weixin_66461496/category_12673810.html 点击跳转
信奥赛C++普及组csp-j初赛&复赛真题题解(持续更新): https://blog.csdn.net/weixin_66461496/category_12808781.html 点击跳转
信奥赛C++提高组csp-s初赛&复赛真题题解(持续更新):
https://blog.csdn.net/weixin_66461496/category_13125089.html 点击跳转
5、GESP C++考级真题题解:

GESP(C++ 一级+二级+三级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12858102.html 点击跳转

GESP(C++ 四级+五级+六级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12869848.html 点击跳转

GESP(C++ 七级+八级)真题题解(持续更新):
https://blog.csdn.net/weixin_66461496/category_13117178.html 点击跳转
· 文末祝福 ·
cpp
#include<bits/stdc++.h>
using namespace std;
int main(){
cout<<"跟着王老师一起学习信奥赛C++";
cout<<" 成就更好的自己! ";
cout<<" csp信奥赛一等奖属于你! ";
return 0;
}
