[题解]NC14503晨跑

晨跑

https://ac.nowcoder.com/acm/problem/14503

题目

“无体育,不清华”、“每天锻炼一小时,健康工作五十年,幸福生活一辈子”

在清华,体育运动绝对是同学们生活中不可或缺的一部分。为了响应学校的号召,模范好学生王队长决定坚持晨跑。不过由于种种原因,每天都早起去跑步不太现实,所以王队长决定每a天晨跑一次。换句话说,假如王队长某天早起去跑了步,之后他会休息a-1天,然后第a天继续去晨跑,并以此类推。

王队长的好朋友小钦和小针深受王队长坚持锻炼的鼓舞,并决定自己也要坚持晨跑。为了适宜自己的情况,小钦决定每b天早起跑步一次,而小针决定每c天早起跑步一次。

某天早晨,王队长、小钦和小针在早起跑步时相遇了,他们非常激动、相互鼓励,共同完成了一次完美的晨跑。为了表述方便,我们把三位同学相遇的这天记为第0天。假设三位同学每次晨跑的时间段和路线都相同,他们想知道,下一次三人在跑步时相遇是第几天。由于三位同学都不会算,所以希望由聪明的你来告诉他们答案。


题解

此题目不难理解,三人以不同的周期跑步,求下一次共同相遇的时间。即求三个数的最小公倍数问题。

求最小公倍数,最容易想到的思路便是暴力求解,即从三个数中找出最大的一个数,从这个数开始不断递增,第一个能够被这三个数同时整除的数,即为所求最小公倍数。

暴力法题解代码(超时)

typedef long long ll;
ll solve(ll a,ll b,ll c){
    ll i = max(max(a,b),c);
    while(!(i % a == 0 && i % b == 0 && i % c == 0)){
        i++;
    }
    return i;
}
分析

这个方法思路简单,向上递增,逐个做匹配。但是该算法效率低下,由于题目输入规模可能较大1≤a,b,c≤100000,运用该算***超时。

即使将该暴力算法优化,在数据规模较大时,超时问题依然严重。

我们不得不考虑更加优秀的算法。

那么问题来了,有什么更加优秀的算法呢?

注意:已知两个数的最大公约数,只需要一步即可得到其最小公倍数。而想得到两数的最大公约数,有著名的欧几里得算法更相减损术

所以我们可以:

  • 使用欧几里得算法求最大公约数,再由最大公约数求出最小公倍数
  • 使用更相减损术求最大公约数,再由最大公约数求出最小公倍数

更相减损术题解代码

#include<cstdio>
using namespace std;
typedef long long ll;
ll solve(ll a,ll b){
    ll ta = a,tb = b;
    while(a != b){
        if(a > b)
            a -= b;
        else
            b -= a;
    }
    return ta * tb / a;
}
int main(){
    ll a[3];
    scanf("%lld%lld%lld",&a[0],&a[1],&a[2]);
    printf("%lld\n",solve(solve(a[0],a[1]),a[2]));
    return 0;
}

分析

更相减损术又称辗转相减法,出自《九章算术》,是一种求最大公约数的算法。

原文:可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之。

译:如果一个分数能被2约分,则用2约分,否则取分数的分子和分母,用大数减小数,再取两数差和减数,反复相减,直至差与减数相等,用这个相等的数来约分。

注意:更相减损术最初是用来约分的。而两个数的最大公约数,等于第一步中约掉的若干个2的积与第二步中等数的乘积。

欧几里得算法题解代码

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;

ll solve(ll a,ll b){
    ll ta = a,tb = b;
    if(a < b)
        swap(a,b);
    while(b){
        ll t = b;
        b = a % b;
        a = t;
    }
    return ta * tb / a;
}
int main(){
    ll a[3];
    scanf("%lld%lld%lld",&a[0],&a[1],&a[2]);
    printf("%lld\n",solve(a[0],solve(a[1],a[2])));
    return 0;
}

分析

欧几里得算法又称辗转相除法,由欧几里得最早记载,可用于求两个非负数的最大公约数。

基本的思路为:

gcd(a,b) = gcd(b,a mod b)

即:
小数除大数,余数变除数,除数变被除数。反复做除,当余数为0,除数即为最大公约数。


该题解为本人原创。
创作不易,转载请说明出处。

全部评论

相关推荐

不愿透露姓名的神秘牛友
07-11 15:37
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
07-11 12:31
以前小时候我最痛恨出轨、偷情的人,无论男女,为什么会出轨?现在我成了自己最讨厌的人,没想到分享的东西在牛客会被这么多人看,大家的评价都很中肯,我也认同,想过一一回复,但我还是收声了,我想我应该说说这件事,这件事一直压在我心里,是个很大的心结,上面说了人为什么出轨,我大概能明白了。我们大一下半年开始恋爱,开始恋爱,我给出了我铭记3年的承诺,我对她好一辈子,我永远不会背叛,我责任心太重,我觉得跟了我,我就要照顾她一辈子,我们在一起3年我都没有碰过她,她说往东我就往东,她说什么我做什么,她要我干什么,我就干什么!在学校很美好,中途也出过一些小插曲,比如男闺蜜、男闺蜜2号等等等。但我都强迫她改掉了,我...
牛客刘北:两个缺爱的人是没有办法好好在一起的,但世界上哪有什么是非对错?你后悔你们在一起了,但是刚刚在一起的美好也是真的呀,因为其他人的出现,你开始想要了最开始的自己,你的确对不起自己,21岁的你望高物远,你完全可以不谈恋爱,去过你想要的生活,你向往自由,在一起之后,你要想的不是一个人,而是两个人,你不是变心了,就像你说的,你受够了,你不想包容了,冷静几天是你最优的选择,爱人先爱己。
社会教会你的第一课
点赞 评论 收藏
分享
仁者伍敌:牛子这些人还会点一个自动回复,boss都不带回复的
点赞 评论 收藏
分享
评论
7
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务