题意:题目给出n,k分别代表在这个环中饭店的个数和两个饭店相离的距离。然后再给出一组a,b分别代表在某一点s里最近饭店的距离和在这个s点走一步之后到达的点离最近饭店的距离。
然后问这个人再次走回到s点的最大步数跟最小步数。。。。由题意可知 城市点数有 n*k个,那么我们如何去确定当前的s点的可能值呢?
枚举可得!!!为什么? 饭店的位置在1,1+k,1+2k.......
s的下一个点最近的饭店有两种情况,1:跟离s点最近的饭店是一样的 那么我们就可以求出 l=1+mk+b- s的位置
2:两个的饭店是不一样的,那么就有下一个饭店的值减去b得到 s的下一个点,那么用这个点的坐标减去s的坐标就能得到 l 。s的坐标为 1+mk+a
那么知道步长了就是枚举找答案就对了。
由初等数论可知 从某个点出发,知道步长跟环的大小,那么跑回原来点的位置的次数为 n*m/gcd(n*m,步长)
这道div1“签到题”就可解了 (本蒟蒻发现最近打比赛怎么打都不满意,决定一心磕爆div1来增强自己,奈何这A题搞了三个小时。。。。希望自己能坚持每天都刷div1)
#include <bits/stdc++.h> using namespace std; #define ll long long #define re register const int N=1e6+10; void read(int &a) { a=0; int d=1; char ch; while(ch=getchar(),ch>'9'||ch<'0') if(ch=='-') d=-1; a=ch-'0'; while(ch=getchar(),ch>='0'&&ch<='9') a=a*10+ch-'0'; a*=d; } ll gcd(ll a,ll b) { return !b?a:gcd(b,a%b); } int main() { int n,m,a,b; read(n); read(m); read(a); read(b); a++;///第一个点的坐标不是0,所以a++ ll t=1ll*n*m; ll ans1=-1,ans2=1ll*n*m+1; for(re int i=0;i<n;i++) { ll t1=1ll*i*m+1+b;///算出可能的s+l值 ll t2=1ll*(i+1)*m+1-b; t1-=a;///b所在的位置-a得到步长 t2-=a; ans1=max(ans1,t/gcd(abs(t1),t)); ans2=min(ans2,t/gcd(abs(t1),t)); ans1=max(ans1,t/gcd(abs(t2),t)); ans2=min(ans2,t/gcd(abs(t2),t)); } cout<<ans2<<" "<<ans1<<endl; return 0; }