P1014 [NOIP 1999 普及组] Cantor 表

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

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

输入格式

整数N(1≤N≤10^7)。

输出格式

表中的第 N 项。

输入输出样例

输入 #1复制

7

输出 #1复制

1/4

题目说明:在题目中可能主要是题干中的“Z”字形不太清楚,因为题目中给出的样例是平行排列的,然而应该是斜着放置更好一些,第一行是 1/1;第二行是2/1,1/2;第三行是3/1,2/2,1/3;……类似下去,“Z”字形就和我们生活中所说的“S”型,排列起来是1/1,(向右下偏移)1/2,2/1,(向左下偏移)3/1,2/2,1/3……

int digui(int n_i)
{
    if (n_i == 1) { return 1; }
    else { return  n_i + digui(n_i - 1); }
}

 这个递归函数是为了计算所输入的数n在第几行,题干中第一行有1个数,第二行有2个数,第三行有3个数,第四行有4个数等等!

int n;cin >> n;
int s_pre = 0, i = 1, s = 0;
while (1)
{
    s = i + s_pre;
    if (s >= n)
    {
        break;
    }
    i++;
    s_pre = s;
}

这段代码得到的 i 为数字 n 所在行的上一行。

 int yu = abs(n - digui(i-1));
 if ((i - 1) % 2 == 1)
 {
     int fz = 1;
     int fm = i;
     int ii = 1;
     while (1)
     {
          if (yu == ii) { break; }
          fz++;
          fm--;
          ii++;
     }
     cout << fz << "/" << fm;
 }
 else
 {
     int fz = i;
     int fm = 1;
     int ii = 1;
     while (1)
     {
         if (yu == ii) { break; }
         fz--;
         fm++;
         ii++;
     }
     cout << fz << "/" << fm;
 }

 这段代码是根据上一行是奇数行还是偶数行确定是向右下还是左下偏移!

总的代码如下!!!

#include<iostream>
using namespace std;
int digui(int n_i)
{
    if (n_i == 1) { return 1; }
    else { return  n_i + digui(n_i - 1); }
}
int main()
{
    int n;cin >> n;
    int s_pre = 0, i = 1, s = 0;
    while (1)
    {
        s = i + s_pre;
        if (s >= n)
        {
            break;
        }
        i++;
        s_pre = s;
    }
    int yu = abs(n - digui(i-1));
    if ((i - 1) % 2 == 1)
    {
        int fz = 1;
        int fm = i;
        int ii = 1;
        while (1)
        {
             if (yu == ii) { break; }
             fz++;
             fm--;
             ii++;
        }
        cout << fz << "/" << fm;
    }
    else
    {
        int fz = i;
        int fm = 1;
        int ii = 1;
        while (1)
        {
            if (yu == ii) { break; }
            fz--;
            fm++;
            ii++;
        }
        cout << fz << "/" << fm;
    }
    
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值