HDU 1356(欧几里得模板)

http://acm.hdu.edu.cn/showproblem.php?pid=1356

这是欧几里得的模板题。。。

  1.  [扩展眼欧几里德]给定 a b d找到满足ax+by=d 的令|x|+|y|最小 
  2. | 参考线性同余方程 g=gcd(a,b) , ax0+by0=gcd(a,b) 
  3. | 程的一组解: x=x0*d/g; y=y0*d/g;    
  4. | 方程的全部解:x..=x+b/g*t   y..=y-a/g*t 
  5. | |x|+|y|= | x + b/g*t | + | y - a/g*t | (这里有绝对值,所以要想总体会小,那么里面的值要尽量小)    
  6. | 这个关于t的函数的最小值应该在|y - a/g*t|为零附近,即t=y*g/a 
  7. | 在 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;
} 
View Code
原文地址:https://www.cnblogs.com/huzhenbo113/p/3266710.html