副标题:以为可以脱非扩欧,奈何败于智商不足
题目分析
首先这个
c=a+b
,所以我们可以暂时只考虑
a
和
但是解出了一个解之后是不够的,还要求最优解。
容易意会得到,如果
a′=a/gcd(a,b)
,
b′=b/gcd(a,b)
,那么通过扩欧可以得到一个特解
x0
和
y0
,然后通解可以表示为
x=x0+at
,
y=y0−bt
可以在坐标系上画出两条直线
l1,l2
(注意上式中的
x
不同于坐标系的x轴,x轴准确的说应该是t轴!),并且斜率是一正一负(a,b同正,题目已说)
所以呢,取一个
代码
#include<cstdio>
#include<iostream>
#include<cmath>
#include<climits>
using namespace std;
#define ll long long
ll read(){
ll q=0,w=1;char ch=' ';
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')q=(ll)q*10+(ll)(ch-'0'),ch=getchar();
return q*w;
}
ll exgcd(ll a,ll b,ll &x,ll &y){
if(!b){x=1;y=0;return a;}
ll d=exgcd(b,a%b,x,y),tmp;
tmp=x;x=y;y=tmp-(a/b)*y;
return d;
}
ll s,t,a,b,T,mi;
int main()
{
ll x,y,d,L,i;
T=read();
while(T--){
s=read();t=read();a=read();b=read();
d=exgcd(a,b,x,y);L=abs(t-s);
if(L%d){printf("-1\n");continue;}
ll ans=LLONG_MAX,kl;
x=x*(L/d);y=y*(L/d);a/=d;b/=d;
mi=(y-x)/(a+b);//交点
for(i=mi-1;i<=mi+1;i++){//讨论整点
if(fabs(x+b*i)+fabs(y-a*i)==fabs(x+b*i+y-a*i))
kl=max(x+b*i,y-a*i);
else kl=fabs(x-y+(a+b)*i);//是加号QAQ
ans=min(ans,kl);
}
printf("%lld\n",ans);
}
return 0;
}