我的思路:枚举所有的分数,判断其是否是最简(分母分子最大公约数=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个序列归并即可(相等则取分母最小的一个——这样显然是最简分数)。