题意:
有n*k个城市,每个城市间的距离是1km,在第1,1+k,1+k*2……,1+(n-1)*k个城市中有饭馆,
从城市s出发,每次走过的距离为l,问再次回到s时停了多少站,数量为num,第一次在s不算。
已知在s时离s最近的饭店的距离是a,当走过l后距离最近的饭店的距离是b,已知走的顺序有两种,分为顺时针,逆时针。
求最小的num = x,最大的num = y。
思路:
一开始题目都没读懂 ̄□ ̄||,后来参考别人的代码,先考虑顺时针和逆时针两种情况,
顺时针:(1)s-1 = a,(2)s-1+l = b
逆时针:(1)s-1 = -a,(2) s-1+l = -b。
所以总共四种情况。
将1,2组合得到l的四种情况
a+b,a-b,b-a,-a-b。
l的间距一定是正数,而且肯定大于k,所以可以写成l = k*i+c的形式,
然后枚举i,i的范围是1~n,c肯定是[1,k)范围内,所以对k取余即可。
从s出发经过n*k/gcd(n*k,l),次回到s,所以枚举所有情况就能求出最终的最小次数和最大次数。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 100100;
typedef long long LL;
LL MIN(LL x,LL y){
return x<y?x:y;
}
LL MAX(LL x,LL y){
return x>y?x:y;
}
LL Gcd(LL x,LL y){
return y==0?x:Gcd(y,x%y);
}
int main(void)
{
LL n,k,a,b,i,j;
scanf("%lld%lld%lld%lld",&n,&k,&a,&b);
LL f[4];
f[0] = a+b;
f[1] = a-b;
f[2] = -a+b;
f[3] = -a-b;
LL x = 1e18+5,y = -1;
for(i=0;i<n;i++){
for(j=0;j<4;j++){
LL c = (f[j]+k)%k;
LL tp = (i*k+c);
x = MIN(x,n*k/Gcd(n*k,tp));
y = MAX(y,n*k/Gcd(n*k,tp));
}
}
printf("%lld %lld\n",x,y);
return 0;
}