Cantor的数表

如下列数,第一项是1/1,第二项是1/2,第三项是2/1,第四项是3/1,第五项是2/2.........

输入n,输出第n项。

1/1  1/2  1/3  1/4  1/5

2/1  2/2  2/3  2/4

3/1  3/2  3/3

4/1  4/2

5/1

样例输入

3

14

7

12345

样例输出

2/1

2/4

1/4

59/99

解题思路:

数表提示我们按照斜线分类,第一条有1个数,第二条有2个数,第三条有3个数。。。。。。。第i条有i个数。

前i条一共有s(k) = 1/2k(k+1)个数。

那么n在哪条斜线上呢?我们只要找到最小的正整数k,使得n <= s(k),那么n就是第k条斜线上倒数第s(k)-n+1个元素,第k条斜线倒数第i个

元素是i/(k+1-i);

 

//
//  main.cpp
//  c++prime
//
//  Created by SJCHEN on 2019/1/19.
//  Copyright © 2019 SJCHEN. All rights reserved.
//

#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdio>
using namespace std;

int main()
{
    int n;
    while (scanf("%d", &n) == 1) {
        int k = 1, s = 0;
        for (;;) {
            s += k;
            if (s >= n) {
                if(k % 2 == 0)
                    cout << k-s+n << "/" << s-n+1 << endl;
                else cout << s-n+1 << "/" << k-s+n << endl;
                break;
            }
            k++;
        }
    }
    return 0;
}

 

 

当然我们也可以用代数去做

n <= s(k) = 1/2k(k+1) = k2+k-2n >= 0

k -(-1-sqrt(1+8*n))/2 >= 0, 这样我们就可以求出k

 

//
//  main.cpp
//  c++prime
//
//  Created by SJCHEN on 2019/1/19.
//  Copyright © 2019 SJCHEN. All rights reserved.
//

#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdio>
using namespace std;

int main()
{
    int n;
    while (scanf("%d",&n) == 1) {
        int k = (int)floor((sqrt(8.0*n + 1)-1)/2-1e-9) + 1;
        int s = k*(k+1)/2;
        if (k % 2 == 0)
            printf("%d/%d\n",k-s+n,s-n+1);
        else printf("%d/%d\n",s-n+1,k-s+n);
    }
    return 0;
}

 

posted @ 2019-03-27 09:35  codeSJCHEN  阅读(285)  评论(0编辑  收藏  举报