题解 P4057 【[Code+#1]晨跑】
fallingdust · · 题解
这题是一道很简单的最小公倍数问题,那么就来普及一下关于最小公倍数的知识点吧。(神犇勿喷,鉴于是写题解,所以就写得细一点)
首先,了解一下最大公约数——GCD。
1:辗转相除法
辗转相除法, 又名 欧几里德算法(Euclidean algorithm)
设两数为a、b(a>b),用gcd(a,b)表示a,b的 最大公约数,r=a (mod b) 为a除以b的余数,k为a除以b的商,即a÷b=k .......r。辗转相除法即是要证明gcd(a,b)=gcd(b,r)。
第一步:令c=gcd(a,b),则设a=mc,b=nc
第二步:根据前提可知r =a-kb=mc-knc=(m-kn)c
第三步:根据第二步结果可知c也是r的因数
第四步:可以断定m-kn与n 互质(假设m-kn=xd,n=yd (d>1),则m=kn+xd=kyd+xd=(ky+x)d,则a=mc=(ky+x)cd,b=nc=ycd,则a与b的一个公约数cd>c,故c非a与b的最大公约数,与前面结论矛盾),因此c也是b与r的最大公约数。
从而可知gcd(b,r)=c,继而gcd(a,b)=gcd(b,r)。
其次,了解一下最小公倍数(LCM)
假设:a=10,b=15,求他们的最小公倍数。
先质数分解:
a=25,b=35;
求他们的最小公倍数,若他们互质,则ans=a*b;
但是a,b有共同的因子(最大公约数),所以:
ans=a*b/(gcd(a,b));
现在上代码:
首先:GCD——辗转相除:
long long gcd(long long x,long long y){
if (x%y==0){
return y;
}
return gcd(y,x%y);
}
其次,最小公倍数——LCM:
long long lcm(long long x,long long y){
return x*y/gcd(x,y);
}
注:数据原因,用long long。
原本的最小公倍数是两个数,但是,此题是三个数,也没关系,先求a,b的LCM,记为x,再求x和c的LCM,然后就结束了,输出答案。
完整代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;//头文件
long long a,b,c;//三个晨跑的人(周期)
long long gcd(long long x,long long y){//辗转相除求最大公约数
if (x%y==0){
return y;
}
return gcd(y,x%y);//重点
}
long long lcm(long long x,long long y){//最小公倍数(用GCD求)
return x*y/gcd(x,y);
}
int main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
scanf ("%lld%lld%lld",&a,&b,&c);//读入
long long ans=0;
ans=lcm(a,lcm(b,c));//直接求答案
cout<<ans<<endl;//输出
return 0;
}