[51nod1187][类欧几里得算法]寻找分数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Rose_max/article/details/83212841

Description

给出 a,b,c,d, 找一个分数p/q,使得a/b < p/q <
c/d,并且q最小。例如:1/3同1/2之间,符合条件且分母最小的分数是2/5。(如果q相同,输出p最小的)

Input

第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 10000) 第2 - T +
1行:每行4个数,a,b,c,d,中间用空格分隔。(1 <= a,b,c,d <= 10^9)

Output

输出共T行,对应符合条件的分数。

Sample Input

4
1 3 1 2
2 1 3 1
2 1 4 1

1000 1001 1001 1002

Sample Output

2/5
5/2
3/1
2001/2003

题解

这是一个类似gcd的算法
不妨设函数 F ( a , b , c , d ) F(a,b,c,d) 表示该状态下的答案
a = 0 a=0 ,显然只需满足 P Q &lt; C D \frac{P}{Q}&lt;\frac{C}{D} P = 1 P=1 时有最优解 Q = D C Q=\frac{D}{C}
a &gt; = b a&gt;=b ,前面是一个假分数,我们化为真分数的形式进入转移 F ( a % b , b , c d ( a b ) , d ) F(a\%b,b,c-d*(\frac{a}{b}),d) ,最后加上
c &gt; d c&gt;d ,此时不满足前两个条件,显然有 a b &lt; 1 \frac{a}{b}&lt;1 ,返回 P = Q = 1 P=Q=1
三个条件没有任意一个满足时,原式为 a b &lt; p q &lt; c d \frac{a}{b}&lt;\frac{p}{q}&lt;\frac{c}{d}
取倒数,转为 d c &lt; q p &lt; b a \frac{d}{c}&lt;\frac{q}{p}&lt;\frac{b}{a} ,进入转移 F ( d , c , b , a ) F(d,c,b,a) ,返回时将 P , Q P,Q 交换
观察到每次对另一个数取模及交换,称为类欧几里得算法

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#define LL long long
#define mp(x,y) make_pair(x,y)
using namespace std;
inline int read()
{
	int f=1,x=0;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline void write(LL x)
{
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+'0');
}
inline void pr1(int x){write(x);printf("/");}
inline void pr2(LL x){write(x);puts("");}
LL a,b,c,d;
struct ph
{
	LL p,q;
	ph(){}
	ph(LL _p,LL _q){p=_p;q=_q;}
};
ph likegcd(LL a,LL b,LL c,LL d)
{
	if(a==0)return ph(1,d*1.0/c*1.0+1);
	else if(a>=b)
	{
		ph tmp=likegcd(a%b,b,c-d*(a/b),d);
		return ph(tmp.p+tmp.q*(a/b),tmp.q);
	}
	else if(c>d)return ph(1,1);
	else
	{
		ph tmp=likegcd(d,c,b,a);
		return ph(tmp.q,tmp.p);
	}
}
int main()
{
	int T=read();while(T--)
	{
		a=read();b=read();c=read();d=read();
		ph re=likegcd(a,b,c,d);
		pr1(re.p);pr2(re.q);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Rose_max/article/details/83212841