EOJ 1852 Solution Report --Ordered Fractions

原创 2014年03月01日 17:26:28

代码看不清的请戳我的原文:http://linus-young.github.io/blog/2014/03/01/eoj-1852-solution-report-ordered-fractions/

csdn这排版没法用了,掀桌(╯‵□′)╯︵┻━┻


1. 问题描述

给定一个数 N , 从小到大列出 0 到 1 之间 分母不超过 N 的最简真分数,包括 0/1, 1/1

2. 解题思路

解法1

最简单的想法,生成所有有效分数,然后对其排序,输出。(0/1 和 1/1 可单独输出) 那么什么是有效分数呢,需要满足以下条件:

  • 分母不超过 N
  • 分子与分母互质
  • 分子小于分母

所以我们用如下循环即可得到有效分数:

1
2
3
4
for(int i = 1; i <= n-1; i++)
  for(int j = i+1; j <= n; j++)
      if(gcd(i, j) == 1) // gcd denotes 最大公约数
            /* store valid fractions here*/

那么问题是怎么存取分数呢?而且输出格式为: $i/j$ 很容易想到 struct 结构体。 因此我们定义如下结构体来存取分数:

1
2
3
4
struct fraction {
  int numerator;
  int denominator;
};

全部有效分数获得后,排序也很简单了,用个 qsort 或者 sort 即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//
//  main.cpp
//  eoj1852_struct
//
//  Created by whyisyoung on 2/27/14.
//  Copyright (c) 2014 whyisyoung. All rights reserved.
//

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
using namespace std;

struct fraction {
  int numerator;
  int denominator;
}frac[7820];

int gcd(int a, int b)
{
  return (b == 0) ? a : (gcd(b, a % b));
}

int generate_fractions(int n)
{
  int count = 0;

  for(int i = 1; i <= n-1; i++) {
      for(int j = i+1; j <= n; j++) {
          if(gcd(i, j) == 1) {
              frac[count].numerator      = i;
              frac[count++].denominator = j;
          }
      }
  }
  return count;
}

int compare(const void* a, const void* b)
{
  fraction *x = (fraction *)a;
  fraction *y = (fraction *)b;
  double frac_a = x->numerator * 1.0 / x->denominator;
  double frac_b = y->numerator * 1.0 / y->denominator;
  if(frac_a < frac_b)
      return -1;
  if(frac_a > frac_b)
      return 1;
  return 0;
}

int main(int argc, char const *argv[])
{
  int n, count;

  while(scanf("%d", &n) != EOF) {
      count = generate_fractions(n);

      cout << "0/1\n";

      qsort(frac, count, sizeof(frac[0]), compare);

      for(int i = 0; i < count; i++)
          cout << frac[i].numerator << '/' << frac[i].denominator << endl;

      cout << "1/1\n";
  }
  return 0;
}

解法2

其实一开始想到的是把 “i/j” 当作字符串处理的,于是问题就是找小数和字符串的对应关系,这好办,一个 map<double, string>就搞定了,而且由于 map 默认对 key 按升序排序,所以只要把这些有效分数加入到 map 即可,连排序的工作都省了,当然为此付出的代价就是多消耗了一些 memory。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
//
//  main.cpp
//  eoj1852
//
//  Created by whyisyoung on 2/23/14.
//  Copyright (c) 2014 whyisyoung. All rights reserved.
//

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
#include <cstdlib>
#include <string>
#include <cstring>
using namespace std;

map<double, string> frac;

int gcd(int a, int b)
{
  return (b == 0)?a:(gcd(b, a % b));
}

int generate_fractions(int n)
{
    int size = 0;

    for (int i = 1; i <= n-1; ++i) {
      for(int j = i+1; j <= n; j++) {
          if(gcd(i, j) == 1) {
              char cstr[10];
              sprintf(cstr, "%d/%d", i, j); // itoa(i, cstr, 10) is deprecated
              string str(cstr);
              frac[i*1.0 / j] = str;
              size++;
            }
      }
  }
  return size;
}

int main(int argc, char const *argv[])
{
  int n, size;
  while(cin >> n) {
      size = generate_fractions(n);

      cout << "0/1\n";

      map<double, string>::iterator it = frac.begin();

      for( ; it != frac.end(); it++) {
          cout << it->second << endl;
      }

      cout << "1/1\n";
  }
  return 0;
}

解法3

以前肖老师讲的,这题实际就是要输出 farey 数列 有两种生成办法:

递归生成:

1
2
3
4
5
6
7
8
9
int N;
void Feray(int a, int b, int c, int d)
{
  if(b + d > N)
      return ;
  Feray(a, b, a+c, b+d);
  cout << a+c << '/' << b+d << endl;
  Feray(a+c, b+d, c, d);
}

主函数中只需调用这句即可 Feray(0, 1, 1, 1);

迭代生成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void farey(int n)
{
  int pa=0, pb=1, ca=1, cb=n;
  int na, nb;

  printf("%d/%d\n", pa, pb);
  printf("%d/%d\n", ca, cb);
  while(ca!=cb){
      na = (pb+n) / cb * ca - pa;
      nb = (pb+n) / cb * cb - pb;
      printf("%d/%d\n", na, nb);
      pa = ca;
      pb = cb;
      ca = na;
      cb = nb;
  }
}

EOJ 2067 Solution Report - Building Roads

原文地址:http://linus-young.github.io/blog/2014/04/15/eoj-2067-solution-report-building-roads/ ...

EOJ 1855 Solution Report - Expedition

原文地址:http://linus-young.github.io/blog/2014/04/15/eoj-1855-solution-report-expedition/ keyw...

EOJ 1488 Solution Report - Coin Collector

原文地址:http://linus-young.github.io/blog/2014/04/15/eoj-1488-solution-report-coin-collector/ ...

USACO-Section2.1 Ordered Fractions【递归算法】

题目描述:输入一个自然数N,对于一个最简分数a/b(分子和分母互质的分数),满足1...
  • tjj1998
  • tjj1998
  • 2017年06月24日 19:52
  • 153

Ordered Fractions顺序的分数

Ordered Fractions顺序的分数 输入一个自然数 N   请写一个程序来增序输出分母小于等于 N 的既约真分数 PROGRAM NAME: frac1 INPUT FORM...

USACO [2.1] Ordered Fractions

Ordered Fractions Consider the set of all reduced fractions between 0 and 1 inclusivewith denom...
  • shhyzzu
  • shhyzzu
  • 2015年12月09日 15:58
  • 144

usaco Ordered Fractions

看题解看到了Russ的分数加成法,优先dfs左边,回溯输出,再dfs右边。。。。。。。 code: /* ID: yueqiq LANG: C++ TASK: frac1 */ #include ...
  • yueqiq
  • yueqiq
  • 2012年08月09日 15:01
  • 279

Ordered Fractions

Problem: Ordered Fractions Consider the set of all reduced fractions between 0 and 1 inclusi...
  • iby07
  • iby07
  • 2011年09月18日 11:22
  • 503

USACO-Section 2.1 Ordered Fractions(排序)

数据很小,直接将所有数存入数组,然后排序即可。 注意:只有最简分数才放入数组,因为如果它不是最简分数,则它化简后一定能在数组中找到...

USACO 2.1.2 Ordered Fractions

一.题目描述 Consider the set of all reduced fractions between 0 and 1 inclusive with denominators less t...
  • lhyer
  • lhyer
  • 2015年08月03日 00:52
  • 217
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:EOJ 1852 Solution Report --Ordered Fractions
举报原因:
原因补充:

(最多只允许输入30个字)