D. The Beatles(思维+枚举)

D. The Beatles

题意:

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

猜你喜欢

转载自blog.csdn.net/qq_41829060/article/details/89181025