枚举全部分数,用 gcd 约成最简后去重,再按分数值升序排序输出,即法里序列的构造。
OJ: roj
题目 ID: 2022
难度:入门
标签:入门数学排序python
创建: 2026-10-01 03:19
更新: 2026-10-06 09:40
题目描述
输入自然数
样例输入 5,输出 0/1、1/5、1/4、1/3、2/5、1/2、3/5、2/3、3/4、4/5、1/1 各占一行。
思路
枚举分母 0/1 排在开头。
参考代码
Python 版:
python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-10-01 03:19
# update_at: 2026-10-01 03:19
import sys
from math import gcd
def solve() -> None:
data = iter(map(int, sys.stdin.buffer.read().split()))
n = next(data)
# 枚举所有 (分子, 分母),gcd 归约去重;0 只保留 0/1,避免 0/2..0/n 混进来。
# tuple 直接比较是先比分子的,必须按分数值 a/b 排序。
fracs = sorted(
{(a // gcd(a, b), b // gcd(a, b)) for b in range(1, n + 1) for a in range(b + 1)},
key=lambda t: t[0] / t[1],
)
sys.stdout.write(''.join(f'{a}/{b}\n' for a, b in fracs))
if __name__ == "__main__":
solve()C++ 版(同一算法):
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-10-06 09:40
* update_at: 2026-10-06 09:40
*/
// main.cpp:枚举分母不超过 N 的分数,gcd 约分去重后按分数值升序输出。
#include <cstdio>
#include <set>
#include <vector>
#include <algorithm>
typedef long long ll;
std::set<std::pair<ll, ll> > unique_frac; // 约分后的 (分子, 分母) 集合,天然去重
std::vector<std::pair<ll, ll> > fractions; // 去重后的最简分数,排序后输出
// 求 x 与 y 的最大公约数,用于把 a/b 约成最简分数。
ll gcd_ll(ll x, ll y) {
while (y != 0) {
ll temp = x % y;
x = y;
y = temp;
}
return x;
}
// 比较函数:a/b < c/d 等价于 a*d < c*b,用交叉相乘避免浮点误差。
bool frac_less(std::pair<ll, ll> x, std::pair<ll, ll> y) {
return x.first * y.second < y.first * x.second;
}
int main() {
ll n;
std::scanf("%lld", &n);
// 枚举 b 从 1 到 n、a 从 0 到 b,把每个分数约分后丢进集合去重。
ll b, a;
for (b = 1; b <= n; b++) {
for (a = 0; a <= b; a++) {
ll g = gcd_ll(a, b);
unique_frac.insert(std::make_pair(a / g, b / g));
}
}
for (std::set<std::pair<ll, ll> >::iterator it = unique_frac.begin(); it != unique_frac.end(); ++it) {
fractions.push_back(*it);
}
std::sort(fractions.begin(), fractions.end(), frac_less);
for (std::vector<std::pair<ll, ll> >::iterator it = fractions.begin(); it != fractions.end(); ++it) {
std::printf("%lld/%lld\n", it->first, it->second);
}
return 0;
}