• zoj3593One 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,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 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,每次你可以向左或者向右走a,b,a+b的距离,问最少走多少次能从A走到B。
    思路:设A,B之间的距离为dis,a+b=c,那么题目等价于min{|x|+|y| | (ax+by=dis) || (ax+cy=dis) || (bx+cy=dis)  }.注:扩展欧几里德算出来ax+by=gcd(c,d)中的特殊值x,y一定满足|x|+|y|最小,但是如果算的是ax+by=d,(d%gcd(a,b),但是d!=gcd(a,b))那么就不一定|x|+|y|最小,此时要使得x趋近于0,或者使得y趋近于0,这样算出来的k带入然后取几者中的最小值,因为x,y的关系式是一条直线,|x|+|y|=m在直线接近坐标轴的情况下取到最小值。
    
    
    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<string>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    typedef long double ldb;
    #define inf 10000000000000LL
    #define pi acos(-1.0)
    #define MOD 1000000007
    #define maxn 1000005
    ll extend_gcd(ll a,ll b,ll &x,ll &y){
        if(b==0){
            x=1;y=0;return a;
        }
        ll d=extend_gcd(b,a%b,y,x);
        y-=a/b*x;
        return d;
    }
    ll niyuan(ll a,ll n){
        ll x,y;
        ll d=extend_gcd(a,n,x,y);
        if(d==1) return (x%n+n)%n;
        else return -1;
    }
    ll gcd(ll a,ll b){
        return (b>0)?gcd(b,a%b):a;
    }
    
    ll solve(ll a,ll b,ll dis)
    {
        ll x,y,d,x0,y0,ans;
        d=extend_gcd(a,b,x,y);
        if(dis%d!=0)return -1;
        x0=x*dis/d;
        y0=y*dis/d;
        ll aa,bb;
        aa=a/d;
        bb=b/d;
    
        ll k;
        k=-x0/bb-1;
        ans=abs(x0+bb*k)+abs(y0-aa*k);
    
        k++;
        ans=min(ans,abs(x0+bb*k)+abs(y0-aa*k) );
    
        k++;
        ans=min(ans,abs(x0+bb*k)+abs(y0-aa*k) );
    
    
        k=y0/aa-1;
        ans=min(ans,abs(x0+bb*k)+abs(y0-aa*k) );
    
        k++;
        ans=min(ans,abs(x0+bb*k)+abs(y0-aa*k) );
    
        k++;
        ans=min(ans,abs(x0+bb*k)+abs(y0-aa*k) );
        return ans;
    
    }
    int main()
    {
        int n,m,i,j,T;
        ll x1,x2,a,b,c,x,y;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%lld%lld%lld%lld",&x1,&x2,&a,&b);
            ll dis=abs(x2-x1);
            c=a+b;
            ll ans=solve(a,b,dis);
            ans=min(ans,solve(a,c,dis));
            ans=min(ans,solve(b,c,dis));
            printf("%lld
    ",ans);
        }
        return 0;
    }


  • 相关阅读:
    poj3686 Windys
    poj3155 Hard Life
    luoguP2774 方格取数问题
    poj3469 Dual Core CPU
    poj3281 Dining
    luogu P3410 拍照
    离散化
    最短路(SPFA)
    lower_bound && upper_bound
    gcd
  • 原文地址:https://www.cnblogs.com/herumw/p/9464541.html
Copyright © 2020-2023  润新知