P1014 [NOIP1999 普及组] Cantor 表
题目链接:https://www.luogu.com.cn/problem/P1014
有理数可枚举
In 1873 Cantor proved the rational numbers countable, i.e. they may be placed in one-one correspondence with the natural numbers.
来自:Georg Ferdinand Ludwig Philipp Cantor
1873 年,Cantor 证明了有理数是可枚举的。可枚举指的是,你可以为集合中的每个元素都分配一个唯一的自然数,建立一个一一对应的关系。
有理数具有
我们可以将所有有理数排列在一个表格中,其中
为了对有理数进行编号,我们需要按照某种方式,将元素排成一条线。这里我们从

图片来自:How can the set of the rational numbers be countable if there is no
通过上面的方式,我们为每个有理数都指定了一个编号,下表列出了一部分有理数和其编号,
通过编号 获取有理数
哪一条对角线?
题目中我们需要通过给定的编号
为了获取有理数
假设编号
我们注意到
- 左端点为整数。右端点此时也为整数,所以我们可知
的值必为左端点,即 。如果为右端点减去一个极小值 ,再对其向下取整,我们可以得到, ; - 左端点为小数。我们可以很容易就知道
, 右端点此时也为小数,如果为右端点减去一个极小值 (小于左端点和左端点向下取整的差值),再对其向下取整,我们可以得到, ;
现在,我们已经得到了两个公式。通过任一公式,我们都可以知道元素位于第几条对角线。
对角线上第几个元素?
下一步,我们需要知道这个元素是对角线上的第几个元素。我们已经知道这个元素位于第
分母和分子

图片来自:How can the set of the rational numbers be countable if there is no
我们按照
通过观察,我们发现同一对角线上的分母和分子之和
则对角线上的第一个元素的分子为
代码
通过上面的公式,我们得到最终的代码,
// https://www.luogu.com.cn/problem/P1014
#include <iostream>
#include <cmath>
int main()
{
int N, n, k, p, q;
std::cin >> N;
n = ceil((sqrt(1+8*N)-1)/2);
/* Another way to calculate the diagonal number `n' */
// const double epsilon = 1e-9;
// n = floor((sqrt(1+8*N)+1)/2-epsilon);
k = N-n*(n-1)/2;
if (n&1)
{
p = (n+1) - k;
q = k;
}
else
{
p = k;
q = (n+1) - k;
}
std::cout << p << '/' << q << std::endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】