http://acm.hdu.edu.cn/showproblem.php?pid=1356
这是欧几里得的模板题。。。
- [扩展眼欧几里德]给定 a b d找到满足ax+by=d 的令|x|+|y|最小
- | 参考线性同余方程 g=gcd(a,b) , ax0+by0=gcd(a,b)
- | 程的一组解: x=x0*d/g; y=y0*d/g;
- | 方程的全部解:x..=x+b/g*t y..=y-a/g*t
- | |x|+|y|= | x + b/g*t | + | y - a/g*t | (这里有绝对值,所以要想总体会小,那么里面的值要尽量小)
- | 这个关于t的函数的最小值应该在|y - a/g*t|为零附近,即t=y*g/a
- | 在 y*g/a 附近的两整数点里取t,再直接验证这两点即可。
#include<stdio.h> __int64 x,y; __int64 fabs(__int64 a) { return a>0?a:-a; } __int64 exgcd(__int64 a,__int64 b) { __int64 t,ans; if(b==0) { x=1; y=0; return a; } ans=exgcd(b,a%b); t=x; x=y; y=t-a/b*y; return ans; } int main() { __int64 max,xx,yy,a,b,d,temp,i,flag,aa,bb,t; while(scanf("%I64d%I64d%I64d",&a,&b,&d),a||b||d) { flag=0; if(a<b) { temp=a; a=b; b=temp; flag=1; } temp=exgcd(a,b); x=x*d/temp; y=y*d/temp; max=9999999; t=y*temp/a; for(i=t-1;i<=t+1;i++) { xx=fabs(x+b/temp*i); yy=fabs(y-a/temp*i); if(xx+yy<max) { max=xx+yy; aa=xx; bb=yy; } } if(flag) printf("%I64d %I64d ",bb,aa); else printf("%I64d %I64d ",aa,bb); } return 0; }