• ZOJ Problem Set


    ZOJ Problem Set - 3593

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3593

    One Person Game


    Time Limit: 2 Seconds      Memory Limit: 65536 KB


    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
    
    

    题解:先求ax+by=A-B的解中|x|+|y|最小的一组x,y值,利用拓展欧几里得可求出ax'+by'=gcd(a,b)的x',y'值,仅在A-B是gcd(a,b)的整数倍时,方程有解,令k=(A-B)/gcd(a,b),则可以求出{color{Red} x=x'*k+b/gcd(a,b)*t,y=y'*k-a/gcd(a,b)*t},当两条直线相交时|x|+|y|最小,求出交点对应的t,由于交点可能不是整数,所以将t-1,t,t+1各判断一次,若x,y同号,结果取绝对值大的(因为同向时x+y可以合并为1步),若x,y异号,结果取绝对值之和,通过ans记录所有结果中的最小值。

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #define ll long long
    using namespace std;
    void exgcd(ll a,ll b,ll &gcd,ll &x,ll &y){
            if(!b){
                    gcd=a;x=1;y=0;
            }else{
                    exgcd(b,a%b,gcd,x,y);
                    ll tmp=x;
                    x=y;
                    y=tmp-a/b*y;
            }
    }
    int main(){
            int T;
            ll a,b,A,B,x,y,gcd,ans,t;
            scanf("%d",&T);
            while(T--){
                    scanf("%lld%lld%lld%lld",&A,&B,&a,&b);
                    exgcd(a,b,gcd,x,y);
                    //cout<<x<<"  "<<y<<endl;
                    if((A-B)%gcd)
                            {printf("-1
    ");continue;}
                    x=(A-B)/gcd*x;
                    y=(A-B)/gcd*y;
                    ans=9999999999;
                    a/=gcd,b/=gcd;
                    t=(y-x)/(a+b);
                    //直线x=x+bt与直线y=y-at的距离最近时对应的整数t
                    for(int i=t-1;i<=t+1;i++)//t不一定为整数,左右各取一次
                            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));
                    printf("%lld
    ",ans);
            }
            return 0;
    }
  • 相关阅读:
    解决margin 外边距合并问题
    tsx 校验 以及写法
    tsx 引入文件找不到
    Ubuntu 16.04安装和卸载软件命令
    Java8 中使用Stream 让List 转 Map使用总结
    Java8 Stream流式编程浅析
    浅析IOC 和 DI
    [ Java面试题 ]Java 开发岗面试知识点解析
    Intellij Idea 常用快捷键总结+实用小技巧
    Intellij Idea基础设置
  • 原文地址:https://www.cnblogs.com/aeipyuan/p/10704472.html
Copyright © 2020-2023  润新知