The Balance(使用扩展欧几里得算法)

题目戳这里
根据题意可以知道,此题是利用扩展欧几里得算法求解不定方程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;
}

(这道题看了好久,?,终于整理好了)

发布了21 篇原创文章 · 获赞 1 · 访问量 309

猜你喜欢

转载自blog.csdn.net/qq_44722533/article/details/102555392