首页 > 代码库 > poj 2142 扩展欧几里得

poj 2142 扩展欧几里得

 原题实际上就是求方程a*x+b*y=d的一个特解,要求这个特解满足|x|+|y|最小

套模式+一点YY就行了

 

总结一下这类问题的解法:

对于方程ax+by=c

设tm=gcd(a,b)

先用扩展欧几里得求出方程ax+by=tm的解x0、y0

然后有a*x0+b*y0=tm

令x1=x0*(c/tm),y1=y0*(c/tm)

则a*x1+b*y1=c

x1、y1即原方程的一个特解

这个方程的通解:xi=x1+k*(b/m),yi=y1-k*(a/m)

另:如果要求yi的最小非负解?令r=a/tm,则解y2=(y1%r+r)%r

 

针对本题,求出x1、y1后可以YY一下:

(1):若x1>0,y1>0,

   1.y1-=(a/m),直到y1<0

   2.y1+=(a/m),直到x1<0

(2):若x1<0,y1>0

     y1-=(a/m),直到y1<0

易知最优解一定出现在这一咕噜里头,操作的同时更新最优答案即可。

 1 #include <iostream> 2 #include <cmath> 3 using namespace std; 4  5 int gcd(int a,int b){ 6         if (b==0) return a; 7         return gcd(b,a%b); 8     } 9 10 int extgcd(int a,int b,int& x,int& y){11         int d=a;12         if (b!=0){13             d=extgcd(b,a%b,y,x);14             y-=(a/b)*x;15         }else{16             x=1;y=0;17         }18         return d;19     }20 21 int main()22 {23     int a,b,d,ax,ay,ans;24     while (cin>>a>>b>>d)25     {26         if (a==0 && b==0 && d==0)   break;27         else28         {29             int x,y;30             int tm=extgcd(a,b,x,y);31             int x1=x*(d/tm),y1=y*(d/tm);32             int ra=a/tm,rb=b/tm;33             y1=(y1%ra+ra)%ra;34             x1=(d-y1*b)/a;35             int x2=x1,y2=y1;36             ans=abs(x2)+abs(y2);37             ax=x2;      ay=y2;38             if (x2<0)39             {40                 while (y2>0)41                 {42                     y2-=ra; x2+=rb;43                     if ((abs(y2)+abs(x2))<ans)44                     {45                         ans=abs(y2)+abs(x2);46                         ax=x2;  ay=y2;47                     }48                 }49             }50             else if (x2>0)51             {52                 while (y2>0)53                 {54                     y2-=ra; x2+=rb;55                     if ((abs(y2)+abs(x2))<ans)56                     {57                         ans=abs(y2)+abs(x2);58                         ax=x2;  ay=y2;59                     }60                 }61                 x2=x1;  y2=y1;62                 while (x2>0)63                 {64                     y2+=ra; x2-=rb;65                     if ((abs(y2)+abs(x2))<ans)66                     {67                         ans=abs(y2)+abs(x2);68                         ax=x2;  ay=y2;69                     }70                 }71             }72             cout<<abs(ax)<<" "<<abs(ay)<<endl;73         }74     }75     return 0;76 }
View Code

 

poj 2142 扩展欧几里得