题目描述:
现代数学的著名证明之一是Georg Cantor证明了有理数是可枚举的。他是用下面这一张表来证明这一命题的:
我们以Z字形给上表的每一项编号。第一项是1/1,然后是1/2,2/1,3/1,2/2,…
输入描述:
整数N(1≤N≤10000000)
输出描述:
表中的第N项这道题其实是一道数学问题,先给每一根45。斜线按组标上序号,那么1/1就在直线1 , 2/1就在直线2。
我们假设N在斜线x与x + 1直线中,则通过推算 (1 + x) * x / 2 <= N <= (1 + x) * (2 + x) / 2, 进一步简化后用代码表示为:
int anchor = (int) (sqrt(2.0 * num + 0.25) - 0.5); // 设定锚anchor,即推算中的x但此时出现了两种情况,第一种即在x直线的末尾,另一种则是在x+1直线上;
因此,我引入了sum和index变量用于调节这两种情况;
int sum = (1 + anchor) * anchor / 2; //sum即在x直线及x直线以前所有的数的个数和 int index = num - sum; //num即N,index可以让我们了解具体是在两种情况中的哪种显而易见的是,当index = 0时,所求数就在x尾端,反之,则x+1线上。
但依然有一个严峻的问题摆在我们面前,那就是所求数所在直线的方向问题;
我使用了一个布尔变量解决了这个问题:
if (index == 0) { anchor_dire = (anchor + 1) % 2 == 0 ? false : true; //当其为true时,直线从上往下走,反之,直线则往上走 } else { anchor_dire = (anchor + 1) % 2 == 0 ? true : false; }至此,基本上所有问题都被解决了,我就将源代码奉上了
#include <bits/stdc++.h> using namespace std; int main () { int num; cin >> num; int anchor = (int) (sqrt(2.0 * num + 0.25) - 0.5); int sum = (1 + anchor) * anchor / 2; int index = num - sum; bool anchor_dire; if (index == 0) { anchor_dire = (anchor + 1) % 2 == 0 ? false : true; } else { anchor_dire = (anchor + 1) % 2 == 0 ? true : false; } if (index == 0) { if (!anchor_dire) cout << 1 << '/' << anchor; else cout << anchor << '/' << 1; } else { if (!anchor_dire) cout << anchor + 2 - index << '/' << index; else cout << index << '/' << anchor + 2 - index; } return 0; }