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. (-231 ≤ A, 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 (向左或向右都可以), 问最少需要多少步可以从一个点走到另一个点。不能到达输出-1
此题是扩展欧几里得问题。
我们可以设 走了x步a,走了y步b, ax + by = |A-B|, 扩展欧几里得解出x和y就是可行答案 但不一定是最少的步数。
现在可以假设如果x和y都是正的,也就是说不往回走,这样可以利用题目给的a+b步数进行优化,不管怎么样结果是x和y的较大值,那么假设x = y, 如果x减小,那么y一定增大 因为总路程是不变的,y减小同理,因此可以认为 x = y的时候 两者的较大值最小。
假设x小于0,y大于0,也就是x步往回走,y步正向走。那么这个结果就是abs(x) + abs(y),如果x继续减小说明往回走的多了 相应的y应该增大 那么最后的结果是增大的。
也就是说 x要尽量的增大 y要尽量的减小,可以理解为x与y最接近的时候取得最小步数。
综上两种情况 (x大于0 y小于0 类似第二种) 可以得到最小值的取得在 x == y 处。 但是可能这个点不存在,就要取他的附近两个点作比较,因为扩展欧几里得的特解求出之后 通解是可以求出的。
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#define mod 4294967296
#define MAX 0x3f3f3f3f
#define lson o<<1, l, m
#define rson o<<1|1, m+1, r
#define INFL 0x3f3f3f3f3f3f3f3fLL
#define mem(a) memset(a, 0, sizeof(a))
const double pi = acos(-1.0);
const double eps = 1e-9;
const int N = 10005;
typedef long long ll;
using namespace std;
ll a, b, st, en;
void exgcd(ll a, ll b, ll& d, ll& x, ll& y) {
if(!b) { d = a; x = 1; y = 0; }
else { exgcd(b, a%b, d, y, x); y -= x*(a/b); }
}
ll cal(ll x, ll y) {
if(x * y > 0) return max(abs(x), abs(y));
else return abs(x) + abs(y);
}
int main() {
//freopen("in.txt", "r", stdin);
int T;
cin >> T;
while(T--) {
cin >> st >> en >> a >> b;
ll len = abs(st-en);
ll d, x, y;
exgcd(a, b, d, x, y);
if(len % d) {
puts("-1");
continue;
}
x = x*len/d;
y = y*len/d;
ll t = (y-x)/(a/d + b/d);
ll ans = cal(x + t * (b/d), y - t * (a/d));
ans = min(ans, cal(x + (t+1) * (b/d), y - (t+1) * (a/d)));
ans = min(ans, cal(x + (t-1) * (b/d), y - (t-1) * (a/d)));
cout << ans << endl;
}
return 0;
}