uestc 1722 吴神的表白

时间:2021-11-17 16:42:23
// 这题做的我好难过 不是因为没有思路 而是因为超数据类型范围的事
// ax+by=c a,b,c>0
// 那么该直线经过 1 2 4三个象限
// 2 4 象限的第一整数解肯定是该象限最优解
// 1 象限的话 x,y尽可能接近 那么解就在该 x与y接近的附近
// 因为 第一象限的解 是 max(x,y) 所联立 x=y 与 ax+by=c =>x=c/(a+b) 枚举该点附近的 几个点就是最优解了
// 也可以 求出 x0 y0特解后 利用 x0-b't=y0+a't 求出 x=x0-((x0-y0)/(a'+b')*b')
// 这两种方法都可以 不过我建议用第一种 因为我在第二种方法上吃亏了
// 因为运算过程结果可能超过 long long
// 坑、、、、、
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <string.h>
using namespace std;
#define MOD 1000000007
#define maxn 1000010
#define maxm 48010
#define LL long long
LL d,x,y;
LL c;
void extendGcd(LL a,LL b){
if(b==){
d=a;
x=;//c/a;
y=;
}else{
extendGcd(b,a%b);
LL t=x;
x=y;
y=t-a/b*y;
}
}
LL deal(LL xx,LL xy){
if(xx>&&xy>) return max(xx,xy);
if(xx<)xx=-xx;if(xy<)xy=-xy;
return xx+xy;
}
int main(){
int A,B;
LL a,b;
int T;
LL ans;
scanf("%d",&T);
while(T--){
scanf("%d %d",&A,&B);
scanf("%lld %lld",&a,&b);
if(A>B) swap(A,B);
c=B;
c=c-A;
if(c==) {printf("0\n"); continue;}
extendGcd(a,b);
if(c%d!=){printf("-1\n");continue;}
x=x*(c/d);
LL tx,ty,tans;
LL m=b/d,n=a/d;
/* tx=c/(a+b); // 方法一
x=x-((x-tx)/m*m);*/ x=(x%m+m)%m; // 方法二 这里是为了不让下面的 a*x超出 long long 被这坑了好久
y=(c-a*x)/b;
x=x-((x-y)/(n+m))*m; y=(c-a*x)/b;
ans=deal(x,y);
int i;
for(i=-;i<=;i++)
{
tx=x+m*i;
ty=(c-a*tx)/b;
tans=deal(tx,ty);
if(tans<ans){ans=tans;}
}
printf("%lld\n",ans);
}
}