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 to a+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. (-2^31 ≤ A, B < 2^31, 0 < a, b < 2^31)
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,求从A到达B的最小步数。
解题思路: 首先L=fabs(B-A)为我们需要前进的距离,那么题目就能转化为
ax+by=L
ax+(a+b)y=L
bx+(a+b)y=L
然后我们可以归结为只需要求ax+by=L
先用扩展gcd求乘法逆元,求得一组x,y后,求最小的特解x0,y0
x0=x*L/gcd(a,b) y0=y*L/gcd(a,b)
令am=a/gcd,bm=b/gcd,则通解可表示为(x0+k*bm, y0-k*am)。
然后通解可以表示为x=x0+bmt,y=y0−amt
可以在坐标系上画出两条直线l1,l2(注意上式中的x不同于坐标系的x轴,x轴准确的说应该是t轴!),并且斜率是一正一负(a,b同正,题目已说)
所以呢,取一个t,如果x和y异号,答案就是你画一条平行于y轴的直线,它和l1,l2的交点间的距离。如果同号就是在这两条直线上横坐标为t的离x轴远的那个点离x轴的距离,那么意会可得,l1,l2交点处取到最优解,由于交点处的t不一定是整数,所以我们要做一些处理(见代码)
/*************************************************************************
> File Name: zoj3593.cpp
> Author: baozi
> Last modified: 2018年08月14日 星期二 18时39分
> status:AC
************************************************************************/
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
using namespace std;
#define ll long long
ll a,b,A,B,C,c,t1,t2,t3;
ll ex_gcd(ll a,ll b,ll &x,ll &y){
if(!b){
x=1,y=0;
return a;
}
ll gc=ex_gcd(b,a%b,x,y);
ll temp=x;
x=y;
y=temp-a/b*y;
return gc;
}
ll cal(ll a,ll m, ll c){
ll x,y;
ll gc=ex_gcd(a,b,x,y);
if(c%gc!=0) return -1;
x*=c/gc;
y*=c/gc;
a/=gc;b/=gc;
ll mid=(y-x)/(a+b);
ll ans=fabs(x)+fabs(y),k1;
for(int i=mid-1;i<=mid+1;i++){
if(fabs(x+b*i)+fabs(y-a*i)==fabs(x+y+b*i-a*i)){
k1=max(x+b*i,y-a*i);
}
else k1=fabs(x-y+(a+b)*i);
ans=min(ans,k1);
}
return ans;
}
int main(){
int i,j,t;
scanf("%d",&t);
while(t--){
scanf("%lld%lld%lld%lld",&A,&B,&a,&b);
C=fabs(B-A);c=a+b;
t1=cal(a,b,C);
if(t1==-1){
printf("-1\n");
continue;
}
ll ans=t1;
printf("%lld\n",ans);
}
return 0;
}