• ZOJ 3593 One Person Game 【带简单处理的扩展欧几里得】


    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3593


    题意:给定一维坐标的出发点的终点,每次可以向左或向右走a,b或a+b的距离,问是否可达,如可达求最小步数

    分析:这种每步有多种决策,初始感觉可能是DP,然而这个数据大小已经覆盖了整个int的大小,dp显然不现实。考虑到最终总是要求最小步数,某个对于a,b这两种步长最终肯定是只会分别沿着一个方向走的,因此我们先假设只有a,b两种步长可以选择,那么可以用扩展欧几里得求解。求出通解后,考虑到同方向的n个a步长和n个b步长可以合并为n个a+b步长,最终的步长也就是a与b分别步数的最大值;而方向相反的话,就是两个相加。根据线性二元不定方程的解的结构可以知道,以上两种情况要求最小步数,都是在两个步长步数相等的附近取得最小值。

    AC代码:


    //ZJU-3593 One Person Game
    //AC 2016-4-18 20:15:03
    //extent Euclid
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cctype>
    #include <cstdlib>
    #include <cstring>
    #include <vector>
    #include <set>
    #include <string>
    #include <map>
    #include <queue>
    #include <deque>
    #include <list>
    #include <climits>
    #include <sstream>
    #include <stack>
    using namespace std;
    
    #define cls(x) memset(x,0,sizeof x)
    #define inf(x) memset(x,0x3f,sizeof x)
    #define neg(x) memset(x,-1,sizeof x)
    #define ninf(x) memset(x,0xc0,sizeof x)
    #define st0(x) memset(x,false,sizeof x)
    #define st1(x) memset(x,true,sizeof x)
    #define INF 0x3f3f3f3f
    #define lowbit(x) x&(-x)
    #define bug cout<<"here"<<endl;
    //#define debug
    
    long long X,Y;
    long long extgcd(long long a,long long b)
    {
        if(b==0)
        {
            X=1;
            Y=0;
            return a;
        }
        long long ans=extgcd(b,a%b);
        long long temp=Y;
        Y=X-(a/b)*Y;
        X=temp;
        return ans;
    }
    
    int main()
    {
        #ifdef debug
            freopen("E:\Documents\code\input.txt","r",stdin);
            freopen("E:\Documents\code\output.txt","w",stdout);
        #endif
        int T;
        long long A,B,a,b;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%lld %lld %lld %lld",&A,&B,&a,&b);
            long long gcd=abs(extgcd(a,b));
            if((B-A)%gcd)
            {
                printf("-1
    ");
                continue;
            }
            long long t=abs((B-A)/gcd);
            X*=t;
            Y*=t;
            long long sa=abs(b/gcd),sb=abs(a/gcd);
            long long k=(Y-X)/(sa+sb);
            long long res=(long long)INF*(long long)INF;
            long long L=0,R=0;
            for(long long i=-1;i<=1;++i)
            {
                L=X+(k+i)*sa;
                R=Y-(k+i)*sb;
                if((L>=0&&R>=0)||(L<=0&&R<=0))
                    res=min(res,max(abs(L),abs(R)));
                else
                    res=min(res,abs(L)+abs(R));
            }
            printf("%lld
    ",res);
        }
        return 0;
    }
    


  • 相关阅读:
    centos 7 和 centoa 8的区别
    centos7制作U盘启动盘
    juypyter notebook安装
    Centos6安装MariaDB
    提job
    report a bug and update
    runtest提交job
    bug
    ps常用选项
    每日一句
  • 原文地址:https://www.cnblogs.com/DrCarlluo/p/6580621.html
Copyright © 2020-2023  润新知