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
  • 相关阅读:
    初级程序员面试不靠谱指南(三)
    [细节决定B度]之回首一瞥cout<<"Hello,world"<<endl;
    20110310日记wmh
    SliverLight 控件属性的赋值方式
    20110309wmh日记
    20110308wmh日记
    20110307wmh日记
    STOAdiary20110314完成的任务
    20110313wmh日记
    20110311wmh日记
  • 原文地址:https://www.cnblogs.com/Empress/p/4382122.html
Copyright © 2011-2022 走看看