Pentium.Labs

System全家桶:https://zhuanlan.zhihu.com/c_1238468913098731520

导航

poj 2142 扩展欧几里得解ax+by=c

 原题实际上就是求方程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         else
28         {
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

 

posted on 2014-11-02 16:03  Pentium.Labs  阅读(316)  评论(0编辑  收藏  举报



Pentium.Lab Since 1998