题目描述:

现代数学的著名证明之一是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;
}