青蛙的约会(扩展欧几里得)
Description
两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面。它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止。可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置。不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的。但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的。为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面。 我们把这两只青蛙分别叫做青蛙A和青蛙B,并且规定纬度线上东经0度处为原点,由东往西为正方向,单位长度1米,这样我们就得到了一条首尾相接的数轴。设青蛙A的出发点坐标是x,青蛙B的出发点坐标是y。青蛙A一次能跳m米,青蛙B一次能跳n米,两只青蛙跳一次所花费的时间相同。纬度线总长L米。现在要你求出它们跳了几次以后才会碰面。
Input
输入只包括一行5个整数x,y,m,n,L,其中x≠y < 2000000000,0 < m、n < 2000000000,0 < L < 2100000000。
Output
输出碰面所需要的跳跃次数,如果永远不可能碰面则输出一行"Impossible"
Sample Input
1 2 3 4 5
Sample Output
4
解题思路:首先根据题目中所给的信息建模,
两只青蛙跳t次之后碰面 (x + t * m) - (y + t * n) = k * L
未知数为t和k
移项合并后变为 (n-m)*t + k*L = x-y
令 n-m=a
L=b
x-y =c
则 a*t + b*k = c
这是一个两个未知数的不定方程
在这里我们所要求的便是t,并且是最小的非负数t,那么用什么方法呢?
扩展欧几里得!!!
a*x+b*y=gcd(a,b)!!!
利用扩展欧几里得算法求解不定方程a * x + b * y = c的整数解的求解全过程,步骤如下:
1、先计算Gcd(a,b),若c不能被Gcd(a,b)整除,则方程无整数解;否则,在方程两边同时除以Gcd(a,b),得到新的不定方程a' * x + b' * y = c',此时Gcd(a',b')=1;
2、利用扩展欧几里德算法求出方程a' * x + b' * y = 1的一组整数解x0,y0,则c' * x0,c' * y0是方程a' * x + b' * y = c'的一组整数解;
3、根据数论中的相关定理,可得方程a' * x + b' * y = c'的所有整数通解为:
x = c' * x0 + b' * t
y = c' * y0 - a' * t (t=0,1,2,……)
我们通过扩展欧几里得算出的x0只是一个特解,而我们需要的则是一个最小的特解,所以x0有两种可能:一种就是x0就是所求的结果,一种是x0大于所求的结果。对此我们的策略是通过x = c' * x0 + b' * t,令x=0,得到x最小时t的取值t0,这时候再改造通解公式x = c' * x0 - b' * t0,使用减号来替代加号是为了得到一个最小值。这时候得到的x可能是负值,那么就需要再加上一个周期b即可。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define ll long long int 5 using namespace std; 6 ll gcd(ll a,ll b) 7 { 8 if(b==0) 9 { 10 return a; 11 } 12 else 13 { 14 gcd(b,a%b); 15 } 16 } 17 void exgcd(ll a,ll b,ll &x,ll &y) 18 { 19 if(b==0) 20 { 21 x=1; 22 y=0; 23 return ; 24 } 25 exgcd(b,a%b,x,y); 26 ll t=x; 27 x=y; 28 y=t-a/b*y; 29 } 30 int main() 31 { 32 ll x,y,m,n,l,d,r,c,a,b,t,ans; 33 ll xx,yy; 34 scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&l); 35 a=n-m; 36 b=l; 37 c=x-y; 38 d=gcd(a,b); 39 if(c%d!=0) 40 { 41 printf("Impossible\n"); 42 } 43 else 44 { 45 a=a/d; 46 b=b/d; 47 c=c/d; 48 exgcd(a,b,xx,yy); 49 t=c*xx/b;///方程的所有解x=c*xx+b*t,令x=0可以求出x最小时t的取值 50 51 ans=c*xx-t*b; 52 if(ans<0) 53 { 54 ans=ans+b; 55 } 56 printf("%lld\n",ans); 57 } 58 return 0; 59 }