2019年CSP-X复赛真题及题解(T2:鼓掌)

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;
}

功能分析

  1. 输入:从标准输入读取三个正整数 (x, y, n)。
  2. 计算
    • 分别计算 ⌊ 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⌋。
  3. 合并:利用容斥原理得到最终有掌声的秒数。
  4. 输出:将结果输出到标准输出。

更多内容请关注专栏:信奥赛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;
}