uestc 1722 吴神的表白

// 这题做的我好难过 不是因为没有思路 而是因为超数据类型范围的事
// 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==0){ d=a; x=1;//c/a; y=0; }else{ extendGcd(b,a%b); LL t=x; x=y; y=t-a/b*y; } } LL deal(LL xx,LL xy){ if(xx>0&&xy>0) return max(xx,xy); if(xx<0)xx=-xx;if(xy<0)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==0) {printf("0\n"); continue;} extendGcd(a,b); if(c%d!=0){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=-2;i<=2;i++) { tx=x+m*i; ty=(c-a*tx)/b; tans=deal(tx,ty); if(tans<ans){ans=tans;} } printf("%lld\n",ans); } }

 

posted on 2013-07-30 08:35  江财小子  阅读(185)  评论(0编辑  收藏  举报