USACO 2.1 Ordered Fractions
很简单的一道题
直接找出所有的分数,然后按值排序,去除重复的输出。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/*
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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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.找出这些分数之间的规律,然后直接生成
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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");
}