中文题。
关于扩展欧几里德算法的讲解,推荐这篇文章。
思路:设跳 t 次,则 x+mt 是青蛙 A 从坐标原点到终点所走的距离,y+nt 是 B 走的距离,要想碰面,则他们相减一定是地面周长的整数倍,则:(x+mt)-(y+nt)=kl; 变形得:(m-n)t-(y-x)=kL; 即(n-m)t+Lk = x-y. 设 a=n-m, b=L, d = x-y.则可以写成 at+bk=d.这时问题转化成了:求最小正整数 t 满足上式。
根据扩展欧几里德算法可以求出 a*t0+b*k0=gcd(a,b)中 t0,k0 的一组解和 gcd,将 t0,k0,gcd 三个数除以 gcd 乘以 d 后这个式子就变成了原式。所以 t = t0*d/gcd. 但这只是一组解,如何让 t 最小?
观察 at+bk=d 这个式子,可以写成 a(t+bn)+b(k-an) = d. (n 为自然数)。也就是说通解写成了 t+bn,那么对计算出的 t 进行如下运算可以得出最小的 t: t = (t%b+b)%b .
#include<iostream> #include<cmath> #include<queue> #include<cstring> #include<string> #include<map> #include<stack> #include<set> #include<cstdio> #include<algorithm> using namespace std; //返回d=gcd(a,b);x和y对应于等式ax+by=d中的x,y long long ex_gcd(long long a,long long b,long long &x,long long &y){ if(a==0 && b==0) return -1;//无最大公约数 if(b==0){ x=1; y=0; return a; } long long d = ex_gcd(b, a%b, y, x); y -= a/b*x; return d; } int main(){ //freopen("a.txt", "r", stdin); long long x, y, m, n, l, d, xx, yy; while(~scanf("%lld%lld%lld%lld%lld", &x, &y, &m, &n, &l)){ d = ex_gcd(n-m, l, xx, yy); if((x-y)%d != 0) printf("Impossiblen"); else{ xx = xx*(x-y)/d; xx = (xx%l+l)%l; cout << xx << endl; } } return 0; }