题意:一个人要从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可以分别求出这三个方程的解,但求出的这组并非最小的
因此利用枚举斜率 得到的交点为最小的一组解
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }