码迷,mamicode.com
首页 > 其他好文 > 详细

One Person Game(zoj3593+扩展欧几里德)

时间:2015-05-04 23:31:35      阅读:189      评论:0      收藏:0      [点我收藏+]

标签:

One Person Game

Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%lld & %llu

Description

There is an interesting and simple one person game. Suppose there is a number axis under your feet. You are at point A at first and your aim is point B. There are 6 kinds of operations you can perform in one step. That is to go left or right by a,b and c, here c always equals toa+b.

You must arrive B as soon as possible. Please calculate the minimum number of steps.

 

Input

There are multiple test cases. The first line of input is an integer T(0 < T ≤ 1000) indicates the number of test cases. Then T test cases follow. Each test case is represented by a line containing four integers 4 integers A, B, a and b, separated by spaces. (-231A, B < 231, 0 < a, b < 231)

Output

For each test case, output the minimum number of steps. If it‘s impossible to reach point B, output "-1" instead.

Sample Input

2
0 1 1 2
0 1 2 4

 

Sample Output

1
-1

 

 

 

 

 

题意:一维坐标轴,有A和B两个地方,现在从A到B,每次可以向任意方向走a、b或者c的距离,其中c=a+b,问能不能走到B,能的话最少走几次。

思路:c = a+b, C = A-B,则等价于求{|x|+|y| | ax+by=C || ax+cy=C || bx+cy=C}。对于ax+by=C,

用扩展欧几里得算法求得ax+by=gcd(a,b),是否有解可由C是否为gcd的倍数判断。

若有解,原方程的一组解为(x0, y0) = (xx*C/gcd, yy*C/gcd)。

令am=a/gcd,bm=b/gcd,则通解可表示为(x0+k*bm, y0-k*am)。

能使|x|+|y|最小的整点一定是最靠近直线与坐标轴交点的地方,

可以由|x|+|y|=C的图像不断平移看出。

由于负数取整时是先对它的绝对值取整,再添上负号,

所以考虑的范围要是[-x0/bm-1, -x0/bm+1] 、[y0/am-1, y0/am+1]。

 

转载请注明出处:寻找&星空の孩子

 

 

技术分享
 1 #include<stdio.h>
 2 #include<math.h>
 3 #include<algorithm>
 4 #define LL long long
 5 using namespace std;
 6 
 7 LL ans;
 8 void exgcd(LL a,LL b,LL& d,LL& x,LL& y)
 9 {
10     if(!b){d=a;x=1;y=0;}
11     else
12     {
13         exgcd(b,a%b,d,y,x);
14         y-=x*(a/b);
15     }
16 }
17 LL China(LL a,LL b,LL c)
18 {
19     LL x,y,d,bm,am;
20 
21     exgcd(a,b,d,x,y);
22     if(c%d) return -1;
23     bm=b/d;
24     am=a/d;
25     x=x*c/d;
26     y=y*c/d;
27 
28 
29     LL sum=fabs(x)+fabs(y);
30 
31     for(int i=-x/bm-1;i<=-x/bm+1;i++)
32     {
33         LL X=x+bm*i;
34         LL Y=y-am*i;
35         if(i)
36         {
37             LL tmp=fabs(X)+fabs(Y);
38             if(tmp<sum) sum=tmp;
39         }
40     }
41     for(int i=y/am-1;i<=y/am+1;i++)
42     {
43         LL X=x+bm*i;
44         LL Y=y-am*i;
45         if(i)
46         {
47             LL tmp=fabs(X)+fabs(Y);
48             if(tmp<sum) sum=tmp;
49         }
50     }
51     return sum;
52 }
53 
54 
55 int main()
56 {
57     int T;
58     LL A,B,C,a,b,c,d,x,y;
59     scanf("%d",&T);
60     while(T--)
61     {
62         scanf("%lld%lld%lld%lld",&A,&B,&a,&b);
63         c=a+b;
64         C=fabs(A-B);
65 
66         LL t1=China(a,b,C);
67         LL t2=China(a,c,C);
68         LL t3=China(b,c,C);
69 
70         if(t1==-1&&t2==-1&&t3==-1)
71         {
72             printf("-1\n");
73             continue;
74         }
75         if(t1>t2) ans=t2;
76         else ans=t1;
77 
78         if(ans>t3) ans=t3;
79 
80         printf("%lld\n",ans);
81     }
82     return 0;
83 }
View Code

 

One Person Game(zoj3593+扩展欧几里德)

标签:

原文地址:http://www.cnblogs.com/yuyixingkong/p/4477889.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!