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