Consider the set of all reduced fractions between 0 and 1 inclusive with denominators less than or equal to N.
Here is the set when N = 5:
0/1 1/5 1/4 1/3 2/5 1/2 3/5 2/3 3/4 4/5 1/1
Write a program that, given an integer N between 1 and 160 inclusive, prints the fractions in order of increasing magnitude.
PROGRAM NAME: frac1
INPUT FORMAT
One line with a single integer N.
SAMPLE INPUT (file frac1.in)
5
OUTPUT FORMAT
One fraction per line, sorted in order of magnitude.
SAMPLE OUTPUT (file frac1.out)
0/1 1/5 1/4 1/3 2/5 1/2 3/5 2/3 3/4 4/5 1/1
题解:枚举分子和分母。分子的范围为[1,n),分母的范围为(1,n]。假设两个分数a/b和c/d,如果gcd(a,b)==1那么就是符合题目要求的。枚举出符合要求的分数之后需要进行排序,判断a/b是否大于c/d,只需判断a*d>b*c是否成立即可。
View Code
1 /* 2 ID:spcjv51 3 PROG:frac1 4 LANG:C 5 */ 6 #include<stdio.h> 7 #include<math.h> 8 #include<stdlib.h> 9 int a[30000],b[30000]; 10 int gcd(int x,int y) 11 { 12 if(x==0) return 0; 13 if(x%y==0) return y; 14 else 15 return(gcd(y,x%y)); 16 } 17 int main(void) 18 { 19 freopen("frac1.in","r",stdin); 20 freopen("frac1.out","w",stdout); 21 int i,j,ans,n,temp; 22 scanf("%d",&n); 23 ans=0; 24 for(i=1;i<n;i++) 25 for(j=i+1;j<=n;j++) 26 if(gcd(i,j)==1) 27 { 28 ans++; 29 a[ans]=i; 30 b[ans]=j; 31 } 32 for(i=1;i<ans;i++) 33 for(j=i+1;j<=ans;j++) 34 if(a[i]*b[j]>a[j]*b[i]) 35 { 36 temp=a[i]; 37 a[i]=a[j]; 38 a[j]=temp; 39 temp=b[i]; 40 b[i]=b[j]; 41 b[j]=temp; 42 } 43 printf("0/1\n"); 44 for(i=1;i<=ans;i++) 45 printf("%d/%d\n",a[i],b[i]); 46 printf("1/1\n"); 47 return 0; 48 }
官网的题解,效率好高!!!
我们可以把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的大小关系来判断递归边界。
<这是分数加成法!?数学上用于找一个无理数的近似分数>
#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"); }