[数论]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

 

转载于:https://www.cnblogs.com/Empress/p/4382122.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值