水题,枚举加快排,注意舍弃分母和分子可以约分的情况。此外,还有一种类似杨辉三角的数学方法:
可以把0/1和1/1作为“端点”,通过把两个分数的分子相加、分母相加得到的新分数作为中点来递归(如图)
0/1 1/1
1/2
1/3 2/3
1/4 2/5 3/5 3/4
1/5 2/7 3/8 3/7 4/7 5/8 5/7 4/5
每一个分数的分子和分母都是由求和得来的,这意味着我们可以通过判断和与N的大小关系来判断递归边界。
/*
ID: xpli1
PROG: frac1
LANG: C++
*/
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
#define OUT cout
#define IN cin
ofstream fout ("frac1.out");
ifstream fin ("frac1.in");
typedef struct{
char s[8];
double x;
}fraction;
fraction f[8000];
int N;
int num;
int gcd(int a,int b){
if(a < b){
a = a + b;
b = a - b;
a = a - b;
}
if(b == 0)
return a;
else
return gcd(b,a%b);
}
int cmp(const void* lhs,const void* rhs){
fraction* f1 = (fraction*)lhs;
fraction* f2 = (fraction*)rhs;
return f1->x < f2->x ? -1 : 1;
}
bool Find(char* s){
for(int i=0; i<num; i++){
if(strcmp(s,f[i].s) == 0)
return true;
}
return false;
}
void solve(){
sprintf(f[0].s,"0/1");
f[0].x = 0;
sprintf(f[1].s,"1/1");
f[1].x = 1;
num = 2;
int GCD,i,j,ii,jj;
char ss[8];
for(i=1; i<=N; i++){ // 分母
for(j=1; j<i; j++){
GCD = gcd(i,j);
ii = i/GCD;
jj = j/GCD;
sprintf(ss,"%d/%d",jj,ii);
if(Find(ss)) continue;
f[num].x = jj*1.0/ii;
sprintf(f[num].s,"%d/%d",jj,ii);
num++;
}
}
qsort(f,num,sizeof(fraction),cmp);
}
int main()
{
IN >> N;
solve();
for(int i=0; i<num; i++)
OUT << f[i].s << endl;
return 0;
}