zoukankan      html  css  js  c++  java
  • [数论]ZOJ3593 One Person Game

    题意:一个人要从A走到B  只能走a布、b步、(a+b)步,可以往左或右走

         问 最少要走几步,不能走到的输出-1

    可以列出方程 $ax+by=A-B$

    或者     $ax+(a+b)y=A-B$

    或者     $bx+(a+b)y=A-B$

    要取这三个方程的最小的$(x+y)$

    根据$ax+by=gcd(a, b) $

    当$A-B$不是$gcd$的倍数时 就不能走到

    利用ex_gcd可以分别求出这三个方程的解,但求出的这组并非最小的

    因此利用枚举斜率 得到的交点为最小的一组解

     1 LL exgcd(LL a,LL b,LL &x,LL &y)
     2 {
     3     LL d=a;
     4     if(b!=0)
     5     {
     6         d=exgcd(b,a%b,y,x);
     7         y-=(a/b)*x;
     8     }
     9     else  x=1,y=0;
    10     return d;
    11 }
    12 LL Abs(LL x)
    13 {
    14     return x<0? -x:x;
    15 }
    16 LL A;
    17 LL gao(LL a, LL b)
    18 {
    19     LL x, y;
    20     LL g=exgcd(a, b, x, y);
    21     x=x*(A/g), y=y*(A/g);
    22     a/=g, b/=g;
    23 
    24     LL ans=Abs(x)+Abs(y);
    25     for(int i=-10;i<10;i++)
    26         ans=min(ans, Abs(x+(-x/b+i)*b)+Abs(y-(-x/b+i)*a));
    27     for(int i=-10;i<10;i++)
    28         ans=min(ans, Abs(x+(y/a+i)*b)+Abs(y-(y/a+i)*a));
    29     return ans;
    30 }
    31 int main()
    32 {
    33     int t;
    34     LL B,a,b;
    35     cin>>t;
    36     while(t--)
    37     {
    38         cin>>A>>B>>a>>b;
    39         A=Abs(A-B);
    40         if(!A)
    41         {
    42             puts("0");
    43             continue;
    44         }
    45         if(A%__gcd(a, b))
    46         {
    47             puts("-1");
    48             continue;
    49         }
    50         cout<<min(gao(a, b), min(gao(a+b, a), gao(a+b, b)))<<endl;
    51     }
    52     return 0;
    53 }
    ZOJ 3593
  • 相关阅读:
    存储管理:
    小软件推荐:
    python学习之序列化
    python学习之串口编程
    python学习之常用模块
    Linux调试工具strace和gdb常用命令小结
    adjtimex和时钟的几个概念tick,freq,ppm,jiffies
    koji
    top -Hp pid 显示所有的线程
    Neighbour table overflow---- arp表溢出
  • 原文地址:https://www.cnblogs.com/Empress/p/4382122.html
Copyright © 2011-2022 走看看