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; }