USACO Ordered Fractions

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

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

#include 
#include 
#include 
#include 
#include 

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 result;

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

template
int Partition(vector & 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
void QuickSort(vector & 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<

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

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



你可能感兴趣的:(USACO)