orderedfractions - codetrick
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:
http://sdjl.me/index.php/archives/70
while(fin>>n) { p[1].a=0; p[2].a=1; p[1].b=1; p[2].b=1; int cnt=3; for(int i=2;i<=n;i++) for(int j=1;j<i;j++) { p[cnt].a=j+0.0; p[cnt].b=i+0.0; cnt++; } sort(p+1,p+cnt,cmp); fout<<p[1].a<<"/"<<p[1].b<<endl; P tmp = p[1]; for(int i=2;i<cnt;i++) { if(p[i].a/p[i].b==tmp.a/tmp.b) continue; fout<<p[i].a<<"/"<<p[i].b<<endl; tmp=p[i]; } }
X. 利用两层循环进行枚举分子分母,当分子分母最大公约数为1时记录下来。
Java: https://github.com/TomConerly/Competition-Programming/blob/master/USACO/Chapter2/frac1.java
http://blog.csdn.net/keybord_dancer/article/details/40623513
Read full article from orderedfractions - codetrick
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/1Write 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/1http://blog.csdn.net/keybord_dancer/article/details/40623513
我们发现可以把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
每个分数都是由它左边和右边的分数生成的。这种想法有助于在递归过深时跳出。
Update: 据查,这个解法利用了法里数列及其相关性质。详见:资料1 资料2http://sdjl.me/index.php/archives/70
private static int n;
private static int[] numerator = new int[8000];
private static int[] denominator = new int[8000];
private static int ansCount = 0;
private static int[] numerator = new int[8000];
private static int[] denominator = new int[8000];
private static int ansCount = 0;
public static void main(String[] args) throws IOException
{
init();
run();
output();
System.exit(0);
}
{
init();
run();
output();
System.exit(0);
}
private static void run()
{
numerator[ansCount] = 0;
denominator[ansCount] = 1;
ansCount++;
{
numerator[ansCount] = 0;
denominator[ansCount] = 1;
ansCount++;
solve(0, 1, 1, 1);
numerator[ansCount] = 1;
denominator[ansCount] = 1;
ansCount++;
}
denominator[ansCount] = 1;
ansCount++;
}
private static void solve(int n1, int n2, int d1, int d2)
{
if (d1 + d2 > n)
{
return;
}
solve(n1, n1 + n2, d1, d1 + d2);
{
if (d1 + d2 > n)
{
return;
}
solve(n1, n1 + n2, d1, d1 + d2);
numerator[ansCount] = n1 + n2;
denominator[ansCount] = d1 + d2;
ansCount++;
denominator[ansCount] = d1 + d2;
ansCount++;
solve(n1 + n2, n2, d1 + d2, d2);
}
http://jackneus.com/programming-archives/ordered-fractions/}
struct fraction{
int nom, denom;
bool operator < (const fraction & b) const {
return 1.0 * nom / denom < 1.0 * b.nom / b.denom;
}
};
bool isIn(fraction fract, vector<fraction> & a){
for(int i = 0; i < a.size(); i++){
if(a[i].nom == fract.nom && a[i].denom == fract.denom) return true;
}
return false;
}
fraction reduce(fraction fract){
for(int i = fract.nom; i != 0; i--){
if(fract.nom % i == 0 && fract.denom % i == 0){
fract.nom /= i;
fract.denom /= i;
return fract;
}
}
return fract;
}
int main(){
ifstream in("frac1.in");
ofstream out("frac1.out");
int N;
in >> N;
vector<fraction> soluts;
fraction fract;
fract.nom = 0;
fract.denom = 1;
soluts.push_back(fract);
fract.nom = 1;
fract.denom = 1;
soluts.push_back(fract);
for(int i = 1; i <= N; i++){
for(int j = i + 1; j <= N; j++){
fraction fract;
fract.nom = i;
fract.denom = j;
fract = reduce(fract);
if(!isIn(fract, soluts)) soluts.push_back(fract);
}
}
sort(soluts.begin(), soluts.begin() + soluts.size());
for(int i = 0; i < soluts.size(); i++) out << soluts[i].nom << "/" << soluts[i].denom << endl;
}
http://blog.csdn.net/acm_lkl/article/details/44180387while(fin>>n) { p[1].a=0; p[2].a=1; p[1].b=1; p[2].b=1; int cnt=3; for(int i=2;i<=n;i++) for(int j=1;j<i;j++) { p[cnt].a=j+0.0; p[cnt].b=i+0.0; cnt++; } sort(p+1,p+cnt,cmp); fout<<p[1].a<<"/"<<p[1].b<<endl; P tmp = p[1]; for(int i=2;i<cnt;i++) { if(p[i].a/p[i].b==tmp.a/tmp.b) continue; fout<<p[i].a<<"/"<<p[i].b<<endl; tmp=p[i]; } }
X. 利用两层循环进行枚举分子分母,当分子分母最大公约数为1时记录下来。
Java: https://github.com/TomConerly/Competition-Programming/blob/master/USACO/Chapter2/frac1.java
while(~scanf("%d",&n)) { int total=0; //total表示除0/1和1/1外最简分数的数量。 for(int i=1;i<=n;i++) for(int j=1;j<i;j++) if(gcd(i,j)==1) //最大公约数等于1时,说明分子分母互质。 { arry[total].a=j; arry[total++].b=i; } qsort(arry,total,sizeof(arry[0]),cmp); //排序 printf("0/1\n"); for(int i=0;i<total;i++) printf("%d/%d\n",arry[i].a,arry[i].b); printf("1/1\n"); }Read full article from orderedfractions - codetrick