POJ 1061 青蛙的约会(扩展欧几里得)

题目大意:

  就是说,给你两个起始的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\n");
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 }

 

posted @ 2015-04-25 11:50  BYYB_0506  阅读(171)  评论(0编辑  收藏  举报