A-the Beatles

传送门:

题意:题目给出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;
}
原文地址:https://www.cnblogs.com/acm1ruoji/p/10758955.html