题目大意:
就是说,给你两个起始的x和y,然后x每次增加m,y每次增加n,以及长度L,求出最小的变化次数T,有(x+m*T)-(y+n*T)==P*L.
解题思路:
裸裸的扩展欧几里得。
分析:假设跳了T次以后,青蛙1的坐标便是x+m*T,青蛙2的坐标为y+n*T。它们能够相遇的情况为(x+m*T)-(y+n*T)==P*L,其中P为某一个整数,变形一下
得到(n-m)*T+P*L==x-y 我们设a=(n-m),b=L,c=x-y,T=x,P=y.于是便得到ax+by==c。激动啊,这不就是上面一样的式子吗。
直接套用扩展欧几里得函数,得到一组解x,y。由于问题是问最少跳多少次,于是只有x是我们需要的信息。那么再想,x是最小的吗?
答案是可能不是!那么如何得到最小解呢? 我们考虑x的所有解的式子: x=x0+b/d*t。x0是我们刚刚求到的,很显然右边是有个单调函数,当t为某一个与x正负性质相反的数时,可以得到最小的x。 令x的正负性质为正,那么x=x0-b/d*t1 (t1==-t)。令x==0,那么t=x0*d/b,最小的x等于x0减去t*b/d。这里得到的x可能是负数,如果是负数,我们再为它加上一个b/d即是所求答案了!
代码:
1 # include<cstdio> 2 # include<iostream> 3 # include<fstream> 4 # include<algorithm> 5 # include<functional> 6 # include<cstring> 7 # include<string> 8 # include<cstdlib> 9 # include<iomanip> 10 # include<numeric> 11 # include<cctype> 12 # include<cmath> 13 # include<ctime> 14 # include<queue> 15 # include<stack> 16 # include<list> 17 # include<set> 18 # include<map> 19 20 using namespace std; 21 22 const double PI=4.0*atan(1.0); 23 24 typedef long long LL; 25 typedef unsigned long long ULL; 26 27 # define inf 999999999 28 29 LL x,y,a,b,c,d; 30 LL n,m,X,Y,L; 31 32 LL ext_gcd( LL a,LL b ) 33 { 34 LL t,d; 35 if ( b==0 ) 36 { 37 x = 1; 38 y = 0; 39 return a; 40 } 41 d = ext_gcd(b,a%b); 42 t = x; 43 x = y; 44 y = t-(a/b)*y; 45 return d; 46 } 47 48 49 int main(void) 50 { 51 while (cin>>X>>Y>>m>>n>>L ) 52 { 53 a = n-m; 54 b = L; 55 c = X-Y; 56 d = ext_gcd(a,b); 57 if ( c%d!=0 ) 58 { 59 printf("Impossible "); 60 continue; 61 62 } 63 x = x*(c/d); 64 y = y*(c/d); 65 66 LL k = x*d/b; 67 k = x-k*b/d; 68 if ( k<0 ) 69 { 70 k+=b/d; 71 } 72 cout<<k<<endl; 73 } 74 75 76 return 0; 77 }