【POJ】2142 The Balance 数论(扩展欧几里得算法)

【题意】给定a,b,c,在天平左边放置若干重量a的砝码,在天平右边放置若干重量b的砝码,使得天平两端砝码差为c。设放置x个A砝码和y个B砝码,求x+y的最小值。

【算法】数论(扩展欧几里德算法)

【题解】问题转化为求满足方程ax+by=c,|x|+|y|的最小值。

先用扩展欧几里得算法求得通解。

由原方程得答案分布在y=-a/b*x+c/b(a>0,b>0,c>0),因此是k<0,b>0的直线。

由于斜率一定,min{|x|+|y|}一定出现在x轴两侧或y轴两侧,取这四个点判断一下即可。

#include<cstdio>
int ansx,ansy,ans;
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
void exgcd(int a,int b,int &x,int &y){
    if(!b){x=1;y=0;}else{exgcd(b,a%b,y,x);y-=x*(a/b);}
}
void s(int x,int y){
    if(x<0)x=-x;if(y<0)y=-y;
    if(x+y<ans){
        ans=x+y;
        ansx=x;ansy=y;
    }
}
int main(){
    int a,b,c;
    scanf("%d%d%d",&a,&b,&c);
    while(a||b||c){
        int g=gcd(a,b),x,y,X,Y;
        a/=g;b/=g;c/=g;
        exgcd(a,b,x,y);
        ans=0x3f3f3f3f;
        X=(x*c%b+b)%b;Y=(c*g-a*g*X)/(b*g);s(X,Y);
        X-=b;Y+=a;s(X,Y);
        Y=(y*c%a+a)%a;X=(c*g-b*g*Y)/(a*g);s(X,Y);
        Y-=b;X+=a;s(X,Y);
        printf("%d %d\n",ansx,ansy);
        scanf("%d%d%d",&a,&b,&c);
    }
    return 0;
}
View Code

 

由于此题数据比较弱,所以网上很多题解都是最小非负x和y,反例:1 10 29。

转载于:https://www.cnblogs.com/onioncyc/p/6180914.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值