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

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

 

你可能感兴趣的:(game)