刷清橙OJ--A1040.Cantor表

来源:互联网 发布:mysql数据库集群搭建 编辑:程序博客网 时间:2024/06/06 00:05
问题:
A1040. Cantor表
时间限制:1.0s   内存限制:512.0MB  
总提交次数:2237   AC次数:1232   平均分:69.90
问题描述
  Georg Cantor证明了有理数是可列的,他用下面这一张表来证明该命题:
  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
  我们以z字型给上表的每一项编号。第1项是1/1,然后是1/2,2/1,3/1,2/2...
  你的任务是求表中第N项的值。
输入格式
  输入仅一个正整数n(1<=n<=100000)
输出格式
  以分数形式输出表中的第n项(不用约分)
样例输入
7
样例输出
1/4

代码:

#include <iostream>#include <cstring>#include <cctype>#include <algorithm>#include <cmath>using namespace std;int main() {    int n;    int sum, dif;    int x, y;    int i;        cin >> n;        sum = 0;    for (i = 1; sum + i < n; i++) {        sum += i;    }    dif = n - sum - 1;    if (i % 2 == 1) {        y = 1 + dif;        x = i - dif;    } else {        x = 1 + dif;        y = i - dif;    }    printf("%d/%d", x, y);        system("pause");    return 0;}

个人想法:高级版找规律吗。。。

试题讨论中的解题思路:

通过观察,发现这张表有这样几个特征:
1、分子和分母分别代表这个分数在表上的行数和列数
例如说3/2就出现在表的第三行第二个
2、如果将编号单独取出来,可以编成这样一张表
1 2 6 7 15 16
3 5 8 14 17
4 9 13 18
10 12
11
...
进一步对上表进行分析,得到这样几个有趣的发现
对角线上的数的数量是逐一递增的
例如第一条对角线(1)上只有一个数
第二条对角线上(2、3)有两个数
第三条对角线上(4、5、6)有三个数
于是,决定解题方法为尝试找到表中第N项在编号数表(上表)的位置
我们可以借助编号数表的对角线
第一条对角线上的最大的编号是1
第二条对角线上的最大的编号是1+2
第三条对角线上的最大的编号是1+2+3
以此类推
可以通过枚举得到第N项在第几条对角线上
通过观察,发现
第奇数条对角线上的编号的增长方向是向右上角的
第偶数条对角线上的编号的增长方向是向左下角的
之后就可以利用枚举出的最大编号与N的差,和N项所在的对角线的编号增长方向逆推出第N向在数表上的位置了 
顺带附一张图帮助大家理解



原创粉丝点击