P1014 [NOIP1999 普及组] Cantor 表 - 洛谷
这个是我做PTA练习的时候遇见的一道感觉蛮有意思的题,做完练习以后去查了一下发现这道题是洛谷上面的一道原题,所以想分享给大家。
题目描述
现代数学的著名证明之一是 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/2,2/1,3/1,2/2,…
输入输出样例
输入:7
输出:1/4
因为自己没有学过算法,所有只能用找规律的方式来和大家分享这道题,其实用算法来做这道题很简单(如果大家有更好的方法希望可以教教我哦)。
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相加为2;第二斜竖,1+2和
2+1都为3;第三斜竖,1+3、2+2、3+1都是4,之后的几条斜竖同理为5、6、7······
第一斜竖往右走,第二斜竖先往左下再向下走,第三斜竖先往右上再往右走,第四斜竖先往
左下再往下走······
可以看出两个数相加为双数时,/左边的数为1就往右走,否则往左下走,直到左边的数等于
它所在行数,/右边的数为1往下走,否则 往右上走,直到右边的数等于它所在列数。
通过上面对题目的分析就可以写出代码啦。
#include<bits/stdc++.h>
using namespace std;
int main(){
int a, b, n;
while(cin >> n){
a = b = 1;
for(int i = 1; i < n; i ++){
// 两个数相加为偶数时
if((a + b) % 2 == 0){
if(a == 1) b++; // “/”左边的数为1时右移
else{ // 往左下移
a --;
b ++;
}
}
// 两个数相加为奇数时
else if((a + b) % 2 != 0){
if(b == 1) a++; // “/”右边的数为1时左移
else{ // 往右上移
a ++;
b --;
}
}
}
cout << a << '/' << b << endl;
}
}
在做完这道题之后,我又遇到了一个类似于这道题的进阶版的题,大家也可以来试一试,编程实现如下图所示的蛇形填数。
输入格式:
输入一个正整数,表示N*N的方阵。
输出格式:
输出蛇形填数后的N*N方阵,每个数字占4列宽。
输入样例:
在这里给出一组输入。例如:7
输出样例:
在这里给出相应的输出。例如:
1 3 4 10 11 21 22
2 5 9 12 20 23 34
6 8 13 19 24 33 35
7 14 18 25 32 36 43
15 17 26 31 37 42 44
16 27 30 38 41 45 48
28 29 39 40 46 47 49