P1618.Cantor表

原题地址https://www.luogu.com.cn/problem/P1014

现代数学的著名证明之一是Georg Cantor证明了有理数是可枚举的。他是用下面这一张表来证明这一命题的:

1/11/2 , 1/311/41/5, …

2/12/2 , 2/32/4, …

3/1 , 3/23/3, …

4/14/2, …

5/1, …

… 我们以Z字形给上表的每一项编号。第一项是1/1,然后是1/22/13/12/2,…

输入格式  整数N1N10000000)

输出格式  表中的第N项。

 

大体是这样:

(1)1/1    →   (2)1/2       (6)1/3   →  (7)1/4     (15)1/5, …

             ↙              ↗              ↙            ↗

(3)2/1,         (5)2/2       (8)2/3         (14)2/4, …

     ↓      ↗              ↙               ↗

(4)3/1          (9)3/2        (13)3/3, …

             ↙              ↗

(10)4/1        (12)4/2, …

     ↓       ↗

(11)5/1, …

斜着看感觉像开封菜(kfc)里的冰激凌,一层层地堆上去 别想歪了,我是会联想到sh*t的那种人吗?

首先,设分子是a(初始值1),分母是b(初始值1),当前所在的序数为i(初始值为1,每次操作+1,直到加到所输数字N)。

    
int a=1,b=1,i=1;
int n; cin>>n; if(n==1) { cout<<"1/1";//特殊情况不用过多考虑 return 0; }

 

再看具体操作。不难发现,如果分子是1(第一行),那么标号的路径会在分母为偶数时转向左下方,分母为奇数时往前一步。

同理,分母是1时(第一列),那么标号的路径会在分子为偶数时转向右上方,分子为奇数时往下一步。

那么如果分子分母都不是1呢?这些分数可以归纳为向右上走和向左下走。这两种情况分别对应什么条件呢?

对!分子分母之和为偶数时向右上走,为奇数时向左下走!当分子分母有一个为1时(到达边界),那么再按分子、分母为1的情况处理。

代码如下:

#include
using namespace std;
int a=1,b=1,i=1;
int main()
{
    int n;
    cin>>n;
    if(n==1)
    {
        cout<<"1/1";
        return 0;
    }
    do
    {
        if((a+b)%2==0)//向右上走
        {
            if(a!=1)//没到达边界
            {
                a--;b++;//往右(b大1)上(a小1)
            } 
            else//到达边界,往下走
            {
                b++;
            }
        }
        else//向左下走
        {
            if(b!=1)//没到达边界
            {
                a++;b--;//往左(b小1)下(a大1)    
            }
            else//到达边界,往前
            {
                a++;
            }
        } 
                i++;
    }while(i<n);
    cout<"/"<<b;
    return 0;
}

 

 

 

 

 

 

 

 

你可能感兴趣的:(P1618.Cantor表)