很简单的一道题
直接找出所有的分数,然后按值排序,去除重复的输出。
/*
ID: superbi1
LANG: C
TASK: frac1
*/
#include < stdio.h >
#include < string .h >
#include < stdlib.h >
#include < math.h >
#define NL 160*161
#define EP 1e-10
struct Fct{
int a, b;
double val;
}f[NL];
int nf;
int gcd( int a, int b)
{
if (b == 0 ) return a;
return gcd(b, a % b);
}
int cmp( const void * a, const void * b)
{
struct Fct * x = ( struct Fct * )a;
struct Fct * y = ( struct Fct * )b;
if (fabs(x -> val - y -> val) < EP) return 0 ;
else if (x -> val < y -> val) return - 1 ;
else return 1 ;
}
int cmp1( struct Fct * a, struct Fct * b)
{
return a -> a - a -> b;
}
int main()
{
FILE * in = fopen( " frac1.in " , " r " );
FILE * out = fopen( " frac1.out " , " w " );
int n;
int I, K;
int a, b;
fscanf( in , " %d " , & n);
nf = 0 ;
f[nf].a = 0 ;
f[nf].b = 1 ;
f[nf ++ ].val = 0 ;
f[nf].a = 1 ;
f[nf].b = 1 ;
f[nf ++ ].val = 1 ;
for (I = 1 ; I <= n; I ++ ) {
for (K = 1 ; K < I; K ++ ) {
int g = gcd(I, K);
f[nf].a = K / g;
f[nf].b = I / g;
f[nf ++ ].val = K * 1.0 / I;
}
}
qsort(f, nf, sizeof (f[ 0 ]), cmp);
a = f[ 0 ].a;
b = f[ 0 ].b;
for (I = 1 ; I < nf; I ++ ) {
if (a == f[I].a && b == f[I].b) continue ;
else {
fprintf( out , " %d/%d\n " , a, b);
a = f[I].a;
b = f[I].b;
}
}
fprintf( out , " %d/%d\n " , a, b);
return 0 ;
}
改进:
1.发现这些分数的分子和分母互素
2.排序的时候的小技巧:p1/q1 = p2/q2 --> p1*q2 = p2*q1
#include < fstream.h >
#include < stdlib.h >
struct fraction {
int numerator;
int denominator;
};
bool rprime( int a, int b){
int r = a % b;
while (r != 0 ){
a = b;
b = r;
r = a % b;
}
return (b == 1 );
}
int fraccompare ( struct fraction * p, struct fraction * q) {
return p -> numerator * q -> denominator - p -> denominator * q -> numerator;
}
int main(){
int found = 0 ;
struct fraction fract[ 25600 ];
ifstream filein( " frac1.in " );
int n;
filein >> n;
filein.close();
for ( int bot = 1 ; bot <= n; ++ bot){
for ( int top = 0 ; top <= bot; ++ top){
if (rprime(top,bot)){
fract[found].numerator = top;
fract[found ++ ].denominator = bot;
}
}
}
qsort(fract, found, sizeof ( struct fraction), fraccompare);
ofstream fileout( " frac1.out " );
for ( int i = 0 ; i < found; ++ i)
fileout << fract[i].numerator << ' / ' << fract[i].denominator << endl;
fileout.close();
exit ( 0 );
}
标程二:
改进:
1.找出这些分数之间的规律,然后直接生成
#include < stdio.h >
#include < stdlib.h >
#include < string .h >
#include < assert.h >
int n;
FILE * fout;
/* print the fractions of denominator <= n between n1/d1 and n2/d2 */
void
genfrac( int n1, int d1, int n2, int d2)
{
if (d1 + d2 > n) /* cut off recursion */
return ;
genfrac(n1,d1, n1 + n2,d1 + d2);
fprintf(fout, " %d/%d\n " , n1 + n2, d1 + d2);
genfrac(n1 + n2,d1 + d2, n2,d2);
}
void
main( void )
{
FILE * fin;
fin = fopen( " frac1.in " , " r " );
fout = fopen( " frac1.out " , " w " );
assert(fin != NULL && fout != NULL);
fscanf(fin, " %d " , & n);
fprintf(fout, " 0/1\n " );
genfrac( 0 , 1 , 1 , 1 );
fprintf(fout, " 1/1\n " );
}