题目戳这里
根据题意可以知道,此题是利用扩展欧几里得算法求解不定方程ax+by=d。
由于本题不需要考虑无解的情况,所以对于不定方程ax+by=d,d是GCD(a,b)的倍数。
首先,不定方程ax+by=d的左式和右式同时除以GCD(a,b),得到a’x+b’y=d’。然后,用扩展欧几里得算法求出’x+b’y=d’的解(x’,y’),则ax+by=d的解就是x=dx,y=dy。接下来,假设将物品放在天平的右边,对两种情况求解。
1)求x是作为解的最小正整数,即a毫克的砝码放在天平左边的最优解(如果y<0,则b毫克的砝码放在天平的右边);
2)求y是作为解的最小正整数,即b毫克的砝码放在天平左边的最优解(如果x<0,则a毫克的砝码放在天平的右边);
最后比较|x|+|y|小的就是结果。
代码如下:
#include<iostream>
#include<cstdio>
using namespace std;
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
int ex_gcd(int a,int b,int & x,/int &y)//使用扩展欧几里得算法计算和返回不定方程ax+by=GCD(a,b)的整数根(x,y)和GCD(a,b)
{
if(b==0)
{
x=1;
y=0;
return a;
}
int d=ex_gcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
return d;
}
int main( )
{
int a,b,d;
int q;
int x,y;
int x1,y1;
int x2,y2;
while(~scanf("%d%d%d",&a,&b,&d))
{
if(a==0&&b==0&&d==0) break;
q=gcd(a,b);//求出a和b的最大公约数
a=a/q;
b=b/q;
d=d/q;//不定式两边同除GCD(a,b)(由于题目一定有解,所以可以整除)得到新不定方程:ax+by=d
//!!!特别注意此时由于a和b已经除以了最大公约数,所以此时的a和b互素
q=ex_gcd(a,b,x,y);//这里计算的是ax+by=GCD(a,b)=1的解
x1=x*d;//由ax+by=1的解可以得到ax+by=d的解
x1=(x1%b+b)%b;//计算x的最小值x1
//推论在此:我们知道不定方程ax+by=c的通解是x=x0+k*b,y=y0-a*k
//由此公式知x的通解是由x每次增减b的整数倍,所以最小整数解=(x0+k*b)%b=(x%b+k*b%b)%b=(x%b+b)%b(这里加b是为了防止出现x为负数的情况
y1=(d-a*x1)/b;
if(y1<0)//若y1小于0,则y1个b毫克的砝码放在天平右边,否则y1个b毫克的砝码放在天平的左边
{
y1=-y1;
}
y2=y*d;
y2=(y2%a+a)%a;
x2=(d-b*y2)/a;
if(x2<0)
{
x2=-x2;
}
if(x1+y1<x2+y2)
{
printf("%d %d\n",x1,y1);
}
else
{
printf("%d %d\n",x2,y2);
}
}
return 0;
}
(这道题看了好久,?,终于整理好了)