题目描述
蒜头君和花椰菜君各做了一个机器人,小蒜和小花。 蒜头君和花椰菜君打算用他们的机器人做个试验,同时放在圆形跑道上的两个点上,各自朝顺时针方向走,直到同时停留在相同的点上为止,即相遇点必须同时是双方走的某一步的终点。 假设圆形跑道的长度为 L,出发点的位置为原点 0,顺时针方向为正方向。这样我们就得到了一条首尾相接的数轴。设小蒜的出发点坐标是 x,小花的出发点坐标是 y。小蒜一步能走 m 米,小花一步能走 n 米。现在请你来算一算,它们走了多少步以后才会碰面。
输入格式
输入一行,输入 5 个整数x,y,m,n,L,其中 x不等于y 且都< 2 *10^9,0<m,n<2×10 ^9 ,0<L<2.1×10^9 。x 和 y 分别表示小蒜和小花出发的位置,m 和 n 分别表示小蒜和小花每一步走的步长,L表示圆形跑道的长度。
输出格式
输出一行,如果小蒜和小花永远不可能碰面,则输出Impossible,否则输出它们需要走多少步才会碰面。
思路
设他们走了k步之后碰面。
(x+km)%L=(y+kn)%L;
k(m-n)+gL=y-x
令m-n = a,L=b,y-x = c;
那就是ka+gb = c;
联想 ax+by = d(最小公倍数)。
c要是d的倍数,那x和y才有解。
所以最后把k求出来,在利用通解的知识就可以求出来,两人要走多少步了。
注:这里面涉及较多对负数的处理。
AC代码
#include <iostream>
#include <cstdio>
using namespace std;
long long int exgcd(long long int a,long long int b,long long int &k,long long int &g){
if(b==0){
k = 1;
g = 0;
return a;
}
long long int r = exgcd(b,a%b,k,g);
long long int t = k;
k = g;
g = t-a/b*g;
return r;
}
int main(){
long long int x,y,m,n,L,k,g;
cin>>x>>y>>m>>n>>L;
long long int a1 = m-n;
long long int c = y-x;
if(a1<0){//对负数的处理
a1 = a1+L;
}
if(c<0){//对负数的处理
c = c+L;
}
long long int b1 = L;
long long int d = exgcd(a1,b1,k,g);
//cout<<(k%b1+b1)%b1;
if(c%d!=0){
printf("Impossible");
}else{
k = (k+(L/d))%(L/d);//对负数的处理
k = k*(c/d)%(L/d);//通解
printf("%lld",k);
}
return 0;
}