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;
}