题目
poj2142
已知
,求最小的
使
成立的
题解
可以通过扩展欧几里德求出一组解
那么通解就是
为系数,
最小值…依靠 经验 咳 感觉 咳咳 画图..得知最小值应当在交点附近(因为题里要求是正数嘛~)
咳 题里还说要求
最小的同时
最小 (我不会说我没看见这个条件..wa了半天..然后对着网上的程序好奇了半天)
这就姑且算作第一种方法吧…
感觉下面这个..好理解【捂脸】
第二种~
由题,只有两种可能:
或者
通过扩展欧几里德我们能求出一组通解(
)
为最小自然数,然后便可以求出
再比较一下大小就可以了
代码
//方法一
#include <cstdio>
#include <algorithm>
using namespace std;
#define inf 0x7fffffff
int exgcd(int a,int b,int &x,int &y){
if(!b){x=1,y=0;return a;}
int c=exgcd(b,a%b,y,x);
y-=a/b*x;
return c;
}
int main(){
freopen("poj2142.in","r",stdin);
int a,b,c,x,y;
while(scanf("%d%d%d",&a,&b,&c)>0 && (a||b||c)){
int d=exgcd(a,b,x,y),t=c/d;
x*=t,y*=t;
int t1=-x*d/b,t2=y*d/a,ans=inf,x0,y0;
for(int i=t1-1;i<=t1+1;i++){
int xx=x+b*i/d,yy=y-a*i/d;
if(abs(xx)+abs(yy)<ans || (abs(xx)+abs(yy)==ans && (a*abs(xx)+b*abs(yy))<(a*abs(x0)+b*abs(y0)))){
x0=abs(xx),y0=abs(yy);
ans=abs(xx)+abs(yy);
}
}
for(int i=t2-1;i<=t2+1;i++){
int xx=x+b*i/d,yy=y-a*i/d;
if(abs(xx)+abs(yy)<ans || (abs(xx)+abs(yy)==ans && (a*abs(xx)+b*abs(yy))<(a*abs(x0)+b*abs(y0)))){
x0=abs(xx),y0=abs(yy);
ans=abs(xx)+abs(yy);
}
}printf("%d %d\n",x0,y0);
}
return 0;
}
//方法二
#include <cstdio>
#include <algorithm>
using namespace std;
#define inf 0x7fffffff
int exgcd(int a,int b,int &x,int &y){
if(!b){x=1,y=0;return a;}
int c=exgcd(b,a%b,y,x);
y-=a/b*x;
return c;
}
int main(){
freopen("poj2142.in","r",stdin);
int a,b,c,x,y;
while(scanf("%d%d%d",&a,&b,&c)>0 && (a||b||c)){
int d=exgcd(a,b,x,y),t=c/d;
int k=b/d;
int x1=(x*t%k+k)%k;
int y1=abs((a*x1-c)/b);
exgcd(b,a,x,y);
k=a/d;
int x2=(x*t%k+k)%k;
int y2=abs((b*x2-c)/a);
if(x1+y1<x2+y2 || (x1+y1==x2+y2 && x1*a+b*y1<x2*b+y2*a)) printf("%d %d\n",x1,y1);
else printf("%d %d\n",y2,x2);
}
return 0;
}