P1516 青蛙的约会

传送门

根据题意可以列出方程:

设走了X步,已经绕了维度线Y圈

那么   nX-mX=LY+(x-y)

稍微转换一下: (n-m)X - LY = x-y

如果设  A=n-m,B=-L,C=x-y

那就变成了AX+BY=C的形式

直接套exgcd就可以得到一组AX+BY=gcd(A,B)的解

根据基本的数学知识,原方程有解当且仅当  gcd(A,B) | C  时

然后把X和Y乘一个C/gcd(A,B)就是原方程的一组解(X,Y)了

然后要注意n-m为负的情况,要把方程两边同时乘-1(A=-A,C=-C)

Y的符号不重要,所以B乘不乘-1都没关系

然后考虑得到一组解后如何求出最小解

可以发现两只青蛙每走L/gcd(L,A)步后就都会回到出发点

所以只要把答案对L/gcd(L,A)取模就是最小解了

还要注意答案是负数的情况,这时答案为 (X%mo+mo)%mo

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
ll exgcd(ll a,ll b,ll &x,ll &y)
{
    if(!b) { x=1,y=0; return a; }
    ll g=exgcd(b,a%b,x,y);
    ll t=x; x=y;
    y=t-a/b*y;
    return g;
}
ll n,m,x,y,L;
ll d,X,Y;
int main()
{
    cin>>x>>y>>m>>n>>L;
    ll A=n-m,B=x-y;//这里的B就是上面说的C
    if(A<0) A=-A,B=-B;
    d=exgcd(A,L,X,Y);
    if(B%d) { printf("Impossible"); return 0; }
    ll ans=X*B/d,mo=L/d;
    printf("%lld",(ans%mo+mo)%mo);
    return 0;
}

 

posted @ 2018-10-12 16:19  LLTYYC  阅读(149)  评论(0编辑  收藏  举报