USACO Ordered Fractions

我的思路:枚举所有的分数,判断其是否是最简(分母分子最大公约数=1),用一个数列记录所有最简分数,然后用快排排序。

/*
ID: wangxin12
PROG: frac1
LANG: C++
*/

#include <iostream>
#include <fstream>
#include <vector>
#include <math.h>
#include <string>

using namespace std;

class Fraction {
public:
	int numerator;
	int denominator;
};

int N;

int GCD(int a, int b) {
	//Euclidean Algo
	if(a < b) return GCD(b, a);

	if(b == 0) return a;
	else return GCD(b, a % b);

	/*
	int r = a % b;
	if(r == 0) return b;
	else return GCD(b ,r); 
	*/
}

vector<Fraction> result;

bool Cmp(Fraction & a, Fraction & b) {
	if( a.numerator * b.denominator >= a.denominator * b.numerator ) return true;
	else return false;
}

template<typename T>
int Partition(vector<T> & f, int start, int finish, bool (cmp)(T & a, T & b)) {
	T key = f[start];
	int left = start + 1;
	int right = finish;

	while(true) {
		
		while(right > left && cmp(f[right],key)) right--;
		while(left < right && !cmp(f[left],key)) left++;
		if(left == right) break;
		T temp = f[left];
		f[left] = f[right];
		f[right] = temp;
	}

	if(cmp(f[left],key)) return start;
	f[start] = f[left];
	f[left] = key;
	return left;
}

template<typename T>
void QuickSort(vector<T> & f, int start, int finish) { 
	if(start >= finish) return;
	int boundary = Partition(f, start, finish, Cmp);
	QuickSort(f, start, boundary - 1);
	QuickSort(f, boundary + 1, finish);
}


int main() {
	ifstream fin("frac1.in");
	fin>>N;
	fin.close();
	
	for(int i = 1; i <= N; i++) {
		for(int j = 0; j <= i; j++) {
			if(GCD(j, i) == 1) {
				Fraction t;
				t.numerator = j;
				t.denominator = i;
				result.push_back(t);
			}
		}
	}
	
	QuickSort(result, 0, result.size() - 1);


	//
	ofstream fout("frac1.out");
	for(int k = 0; k < result.size(); k++) {
		fout<<result[k].numerator<<'/'<<result[k].denominator<<endl;
	}

	fout.close();
    
	return 0;
}

还可以有其他思路,比如:
1.  由于任意两个分数的差一定>=1/(160*159),所以直接把所有分数乘上50880,四舍五入后直接桶排序,而且一边输入一边排,只需要同时记录分子分母就行了,O(n)!!。连化简都省了,遇到相同值就跳过(因为之前必定有一个数值更小的分数等于这个值)

2. 显然,0/i 1/i 2/i...i/i这个序列是有序的对于n个序列归并即可(相等则取分母最小的一个——这样显然是最简分数)。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值