ZOJ - 3593 One Person Game (扩展欧几里得 技巧)@

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,band 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 ABa and b, separated by spaces. (-231 ≤ AB < 231, 0 < ab < 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或c步,c=a+b;问最小步数;

根据公式ax+by=c;,当x,y同号时等于max(x,y),当a,b异号时等于(abs(x)+abs(y)),因为a,b大于0,所以不管x,y同号还是异号都是当x,y,最接近时,答案最小,写出通式

x=x1+b/(gcd)*k,y=y1-a/gcd*k; 假设x,y相等,k=(y-x)/(a+b),因为x,y不一定相等,所以枚举k附近的点


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long LL;
const int N = 1e5+10;

LL exgcd(LL a,LL b,LL &x,LL &y)
{
    if(b==0)
    {
        x=1, y=0;
        return a;
    }
    LL ans=exgcd(b,a%b,x,y);
    LL tmp=x;
    x=y;
    y=tmp-a/b*y;
    return ans;
}

int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        LL A, B, a, b, c, x, y;
        scanf("%lld %lld %lld %lld",&A, &B, &a, &b);
        if(A>B) swap(A,B);
        c=(B-A);
        LL g=exgcd(a,b, x, y);
        if(c%g!=0) puts("-1");
        else
        {
            a/=g, b/=g;
            x*=(c/g), y*=(c/g);
            LL k=(y-x)/(a+b);
            LL ans=10000000000ll;
            for(LL i=k-1;i<=k+1;i++)
            {
                if(abs(x+i*b)+abs(y-i*a)==abs(x+i*b+y-i*a)) ans=min(ans,max(abs(x+i*b),abs(y-i*a)));
                else   ans=min(ans,abs(x+i*b)+abs(y-i*a));
            }
            cout<







你可能感兴趣的:(扩展欧几里德)