1. 程式人生 > >【排序】【USACO2.1.2】順序的分數

【排序】【USACO2.1.2】順序的分數

【問題描述】

  輸入自然數N,對於一個最簡分數 a/b(分子和分母互質的分數),滿足1 <= b <= N,0 <= a/b <= 1,請找出所有滿足條件的分數。

  這有一個例子,當N=5時,所有解為:

   0/1 1/5 1/4 1/3 2/5 1/2 3/5 2/3 3/4 4/5 1/1 

  給定一個自然數N,1<=n<=160,請程式設計按分數值遞增的順序輸出所有解。

  提示:
  ①、0 和任意自然數的最大公約數就是那個自然數。
  ②、互質指最大公約數等於1的兩個自然數。

【輸入格式】

單獨的一行 一個自然數N(1..160)

【輸出格式】

每個分數單獨佔一行,按照大小次序排列 。

【輸入樣例】

5

【輸出樣例】

0/1
1/5
1/4
1/3
2/5
1/2
3/5
2/3
3/4
4/5
1/1     

【資料範圍】
1 <= N <= 160

題目大意:輸入一個正整數n,要求所有滿足1 <= b <= N的最簡真分數。
演算法:列舉+排序+gcd;
由於要滿足題目所給的條件的正整數b有很多,但都在區間[1,n],故在[1,n]上列舉b,由0<=a/b<=1得到0<=a<=b,再用一重迴圈列舉a,每次列舉一個(a,b),都用gcd是否為1判斷a,b是否互質,如果互質就將a,b壓入陣列中,然後根據分數值大小排序。
小技巧:由於本題是分式型排序,為了減小誤差,可以比較分式兩邊交叉相乘的結果(注意比較過程中是否超出int範圍)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#define maxn 165
#define eps 0.0000001
using namespace std;
int n;
struct data
{
    int a,b;
};
vector<data>A;

bool cmp(data a,data b)
{
    return a.a*b.b<b.a*a.b;
}

int
gcd(int a,int b) { return b==0? a:gcd(b,a%b); } int main() { //freopen("my.in","r",stdin); //freopen("my.out","w",stdout); scanf("%d",&n); for(int b=1;b<=n;b++) for(int a=0;a<=b;a++) { if(gcd(a,b)==1) { A.push_back((data){a,b}); } } sort(A.begin(),A.end(),cmp); for(int k=0;k<A.size();k++) printf("%d/%d\n",A[k].a,A[k].b); return 0; }