题意:
有两个机器人,走路的速度是一样的,一个机器人一步走w米,一个机器人一步走b米,现在给出的赛道长最大为t,问在这些长度中,选择哪些长度会导致平局。需要注意的是,如果此时机器人的下一步将会超过剩余赛道长度,那么机器人就不会走这一步。而所谓胜局的情况是在没有平局的情况下,谁离起点最远谁就是赢家。
思路:
首先这道题千万不要被速度给搞晕了,即使速度一样,那么频率也有可能不一样。这时候直接看步数,我们可以很快的找出来当长度为他们的最小公倍数时到达同一位置,还有一种情况就是当长度小于他们中的最小值,那么肯定是平局的。所以长度t可以分成n个lcm块,对于每一个LCM块里面,长度比min(w,b)最小还小的值一定是属于平局的情况,还有每一块的最后一个值,即为w,b的公倍数的一定也是不满足情况的。
讨论要分情况:
当LCM>t时:
这时候t已经是属于块中了,所以直接找到min(t,w-1,b-1)就行了。但是,测试数据绝对都是特别大的数据,单纯的算LCM可能会超出long long。所以直接采用取对数的方法,log(lcm)>log(t); log(lcm)=log(a)+log(b)-log(gcd(a,b));
当LCM<=t时:
此时就可以把长度t进行分块,每一个块的长度是LCM,但是还有情况:即有可能t无法整除LCM,那么对于剩下来的那一部分,如果剩下来的那部分长度是大于min(w,b)的,那么直接把最后剩下的那段长度只取min(w-1,b-1);
#include<iostream>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
#define LL long long
LL t,w,b;
LL gcd(LL a,LL b)
{
if(b==0)
return a;
return gcd(b,a%b);
}
LL LCM(LL a,LL b)
{
return a/gcd(a,b)*b;
}
bool issmall(LL a,LL b,LL t)
{
if(log(a*1.0)+log(b*1.0)-log(gcd(a,b)*1.0)>log(t*1.0))
return 1;
return 0;
}
int main()
{
cin>>t>>w>>b;
LL ans;
if(w==b)
{
ans=t;
}
else if(issmall(w,b,t))
{
ans=min(w-1,min(b-1,t));
}
else
{
LL lcm=LCM(w,b);
LL times=t/lcm;
if(times*lcm+min(w,b)<=t)
{
ans=(times+1)*min(w,b)-1;
}
else
{
ans=times*(min(w,b)-lcm)+t;
}
}
cout<<ans/gcd(ans,t)<<"/"<<t/gcd(ans,t);
return 0;
}