1062 最简分数 (20 point(s))

// 2 points
#include <bits/stdc++.h>
using namespace std;

int gcd(int a, int b){
	return b ? gcd(b, a % b) : a;  
}

int main() {
	int n1, m1, n2, m2, k;
	scanf("%d/%d %d/%d %d", &n1, &m1, &n2, &m2, &k);
	
	// 获取共同的分母和分子范围 
	int small = n1 * m2, large = n2 * m1, deno = m1 * m2;
	if(small > large) swap(small, large);
	// cout << small << ' ' << large << ' ' << deno;
	
	// 遍历范围内所有分子 如果最简分数分母为 K 输出
	for(int i = small + 1, first = 0; i < large; i++){
		int tmp = gcd(i, deno);
		
		if(deno / tmp == k){
			cout << (first++ ? " " : "");
			cout << i / tmp << '/' << deno / tmp;
		}
			
	} 
}
#include <bits/stdc++.h>
using namespace std;

int gcd(int a, int b){
	return b ? gcd(b, a % b) : a;  
}

int main() {
	int n1, m1, n2, m2, k;
	scanf("%d/%d %d/%d %d", &n1, &m1, &n2, &m2, &k);
	// 令左边分数大于右边 
	if(n1 * m2 > n2 * m1){
		swap(n1, n2);
		swap(m1, m2);
	} 
	// num 分子从 1 开始 找到以 K 为分母而 大于 n1/m1 的分数
	int num = 1, first = 0;
	while(num * m1 <= k * n1) num++;
	
	// 当小于 n2/m2 时执行 
	while(num * m2 < k * n2){
		if(gcd(num, k) == 1){
			cout << (first++ ? " " : "");
			cout << num << '/' << k;
		}
		// 分子递增 
		num++;
	} 
}

看了半天题目没看懂这个 “之间” 说的是什么,还以为是用这两个分数做什么加减乘除的运算然后化为最简分式。

看了别人的代码原来是指以这两个分数为范围,写出这个范围中的最简分式分母为 K 的结果。


样例过了,只过了一个测试点2, 0 1 3 4 测试点都没过。

看了别人的代码,然后乱写了几个样例,发现根本没有输出,比如 1/28 29/40 12 。别人的代码可以得到几个关于分母 12 的结果。调试发现得到的分母除以 12 后根本不能得到整数。所以原来思路得到的分母是错误的。分母都得不到 K 什么分子都没有用。

一开始是想对两个分数进行通分,通分后的以两个共同分母的分数遍历大小分子构成的区间,来找到能够化为最简后分母为 K 的分数并输出。

但两个分母相乘的思路是不对的。要将分母变成 K 或者 K 的倍数。但相乘之后不一定是 K 的倍数,能够样例只因为其分母的因数能够凑出 K ,但不能说明其他的数据也可以得到这个结果。

而在给出分数之间的分数不一定以这两个分数通分后的分母作为分母,可能是或大的或小的,只要配合分子就可以。而得到化简后分母为 K 的关键,则必须为 K 或其倍数。所以虽然给出分数区间内的分母可以任意,但是为了满足条件则必须为 K 及其整数。为了简单,用 K 即可。


while(num * m1 <= k * n1) num++

当时忘记写等号,如果不写那么可能会得到 num * m1 == k * n1 的判断。而根据条件 “两个给定分数之间分母为 K 的所有最简分数” 之间意味着不能够取分数相同的结果。否则会卡测试点2。所以要多个等号。

gcd(num, k) == 1

判断是否是最简分数的判断,可以根据最大公约数返回的结果,如果两个都是最简的话,那么必然最大公约数是 1 。

参考代码

测试点2

posted on 2021-09-12 23:29  Atl212  阅读(81)  评论(0)    收藏  举报

导航